簡體   English   中英

使用nameof運算符而不是CallerMemberNameAttribute來通知.NET 4.5.3中的屬性更改有什么好處?

[英]Is there any benefit of using the nameof operator instead of the CallerMemberNameAttribute to notify property changes in .NET 4.5.3?

隨着.NET 4.5.3的出現,WPF開發人員現在有三種(或更多)方法來通知INotifyPropertyChanged接口的屬性更改。 基本上,我的問題是從.NET 4.5開始引入的兩種方法中哪一種是更有效的方式來通知屬性更改以及在WPF中使用這兩種方式是否有任何好處?

背景

對於那些不太熟悉這個主題的人,這里有三個主要方法。 第一個是簡單傳遞字符串的原始的,更容易出錯的方法:

public string TestValue
{
    get { return testValue; }
    set { testValue = value; NotifyPropertyChanged("TestValue"); }
}

protected virtual void NotifyPropertyChanged(string propertyName)
{
    if (PropertyChanged != null)
    {
        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

第二種方法是在.NET 4.5中引入的; CallerMemberNameAttribute

public string TestValue
{
    get { return testValue; }
    set { testValue = value; NotifyPropertyChanged(); }
}

protected virtual void NotifyPropertyChanged([CallerMemberName]string propertyName = "")
{
    if (PropertyChanged != null)
    {
        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

第三個也是最近的方法是(或將很快)作為.NET 4.5.3的一部分在C#6.0中引入; nameof操作

public string TestValue
{
    get { return testValue; }
    set { testValue = value; NotifyPropertyChanged(nameof(TestValue)); }
}

protected virtual void NotifyPropertyChanged(string propertyName)
{
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

我自己的假設是,簡單地傳遞字符串的原始的,更容易出錯的方法將是最有效的,因為我只能想象其他兩種方法使用某種形式的反射。 但是,我真的很想知道其他兩種方法中哪一種更有效,以及在WPF上下文中使用CallerMemberNameAttribute屬性和nameof運算符之間是否存在任何差異。

關於效率:直接使用字符串, CallerMemberNameAttributenameof都完全相同,因為編譯器在編譯時注入了字符串。 沒有任何反思。

我們可以看到使用TryRoslyn CallerMemberNameAttribute生成它

public string TestValue
{
    get { return this.testValue; }
    set { this.testValue = value; this.NotifyPropertyChanged("TestValue"); }
}
protected virtual void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
{
    if (this.PropertyChanged != null)
    {
        this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

這個nameof

public string TestValue
{
    get { return this.testValue; }
    set { this.testValue = value; this.NotifyPropertyChanged("TestValue"); }
}
protected virtual void NotifyPropertyChanged(string propertyName)
{
    if (this.PropertyChanged != null)
    {
        this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

因為在運行時所有選項都只是一個string ,所以WPF上下文沒有問題。

關於便利性: CallerMemberNameAttribute要求您具有可選參數,而nameof沒有,但nameof要求您指定屬性,而CallerMemberNameAttribute則不需要。

我預測這個nameof會變得如此受歡迎,以至於使用它會更加簡單。

CallerMemberNameAttribute只能在被調用函數上使用獲取調用函數的名稱。

nameof運營商超越了這種方式。 它可以在任何地方使用。

如果您只想在WPF數據綁定的范圍內進行推理,請采用以下示例:

public string FullName
{
   get
   {
       return string.Format(
           "{0} {1}",
           this.firstName,
           this.lastName);
   }
}

public string FirstName
{
   get
   {
       return this.firstName;
   }
   set
   {
       if (value != this.firstName)
       {
           this.firstName = value;
           NotifyPropertyChanged(nameof(FirstName));
           NotifyPropertyChanged(nameof(FullName));
        }
   }
}

public string LasttName
{
   get
   {
       return this.lastName;
   }
   set
   {
       if (value != this.lastName)
       {
           this.lastName = value;
           NotifyPropertyChanged(nameof(LasttName));
           NotifyPropertyChanged(nameof(FullName));
        }
   }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM