我正在使用一些现有代码并试图找出在实现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");
}
}
}
答案 0 :(得分:10)
两个版本同样容易出现输入错误。
如果您有一个最新版本的.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();
}
}
}
您在输入错误方面没有任何问题。
答案 1 :(得分:2)
编译器没有优势,因为两者最终都是一个常量值。
我无法想象以这种方式使用代码的真正优势。无论哪种方式很容易弄错,你也不会重复使用那个常量,所以它毫无意义。
我很高兴看到下一版.NET中新的nameof
关键字实现。或者甚至更好,如果可能的话,使用[CallerMemberName]
作为Marc Gravell建议。
在拥有自定义计算属性(例如WPF中)没有自己的getter / setter时,使用nameof
会很有用。
答案 2 :(得分:1)
回答你的问题(试图找出优势):对于了解你的类型并等待特定属性进行更改的观察者来说,有一个优势
void Observe(Customer c)
{
c.PropertyChanged += (s, e) =>
{
if (e.PropertyName == Customer.CustomerIdPropertyName)
{
MessageBox.Show("New id " + Customer.CustomerId);
}
}
}
如果你想进一步:
使用属性选择器表达式填充CustomerIdPropertyName可以避免键入错误。
nameof
关键字(CTP)不需要它。如果你没有这种观察者,CalleMemberNameAttribute
是最简单的方法。
答案 3 :(得分:1)
我想这只是为了避免由拼写错误引起的错误,并尝试使代码更容易阅读。此外,如果更改属性的名称,则意味着更改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字段的引用比在整个项目中搜索魔术字符串更容易)