随着.NET 4.5.3的出现,WPF开发人员现在有三种(或更多种)方式来通知INotifyPropertyChanged
Interface属性更改。基本上,我的问题是从.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
Operator:
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
运算符之间是否存在任何差异
答案 0 :(得分:27)
关于效率:直接使用字符串,CallerMemberNameAttribute
,nameof
都完全相同,因为编译器在编译时注入了字符串。没有任何反思。
我们可以看到使用produces this for 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));
}
}
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
则不需要。{ / p>
我预测nameof
会变得如此受欢迎,以至于使用它会更简单。
答案 1 :(得分:6)
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));
}
}
}