使用字符串常量通知属性更改
本文关键字:属性 通知 常量 字符串 | 更新日期: 2023-09-27 18:19:10
我正在使用一些现有的代码,并试图找出在实现INotifyPropertyChanged接口时使用属性名称的字符串常量的优势(如果有的话)。
例如:
/*
* Why use this instead of string literal
* in OnPropertyChanged below??
*/
public const string CustomerIdPropertyName = "CustomerId";
private int _customerId;
public int CustomerId
{
get
{
return _customerId;
}
set
{
if (_cusomterId != value)
{
_customerId = value;
OnPropertyChanged(CustomerIdPropertyName);
}
}
}
而不是:
private int _customerId;
public int CustomerId
{
get
{
return _customerId;
}
set
{
if (_cusomterId != value)
{
_customerId = value;
OnPropertyChanged("CustomerId");
}
}
}
两个版本同样容易出现输入错误。
如果你使用的是最近的。net版本,你的属性更改处理程序应该是这样的:
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = this.PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
那么你的属性看起来像这样:
private int _customerId;
public int CustomerId
{
get
{
return _customerId;
}
set
{
if (_cusomterId != value)
{
_customerId = value;
this.OnPropertyChanged();
}
}
}
这对编译器没有好处,因为两者最终都是一个常量。
我想象不出这样使用代码有什么真正的好处。这两种方法都很容易出现错别字,而且你不会在任何地方重用这个常量,所以它是没有意义的。
我很想看到新的nameof
关键字在。net的下一个版本中实现。或者,如果可能的话,使用Marc Gravell建议的[CallerMemberName]
更好。
nameof
的使用将是有用的自定义计算属性(如在WPF中),没有自己的getter/setter。
要回答你的问题(试图找出优势):对于知道你的类型并等待特定属性更改的观察者来说,有一个优势
void Observe(Customer c)
{
c.PropertyChanged += (s, e) =>
{
if (e.PropertyName == Customer.CustomerIdPropertyName)
{
MessageBox.Show("New id " + Customer.CustomerId);
}
}
}
如果你想继续:
使用属性选择器表达式来填充CustomerIdPropertyName可以避免输入错误。
你不需要它与nameof
关键字(CTP)。如果你没有这种观察者,CalleMemberNameAttribute
是最简单的方法。
我想这只是为了避免由拼写错误引起的错误,并尝试使代码更容易阅读。此外,如果你改变了属性的名称,这意味着改变const的值将对所有检查属性是否改变的代码起作用。例如,想象一下这样的代码:
public void Main()
{
var obj = new ClassWithNotifier();
obj.OnPropertyChanged += ObjectPropertyChanged;
DoSomethingWithObj(obj);
}
private void ObjectPropertyChanged(string propertyName)
{
switch (propertyName) {
case ClassWithNotifier.CustomerIdPropertyName:
// If the constant changes this will still work
break;
case "SomeOtherPropertyName":
// If you change the property string that is passed here from
// your class ClassWithNotifier then this will now break
break;
}
}
在上面的例子中,不管常量的值是什么,代码都可以工作,如果你想在某个时候改变属性名,那么你只需要改变常量的值,一切都可以正常工作,而不需要找到我们正在检查名称的所有地方(显然,如果你想改变常量变量的名称,那么你仍然需要找到那些引用)。但是查找Public字段的引用要比在整个项目中查找魔术字符串容易)