使用字符串常量更改通知属性

我正在使用一些现有代码,并试图找出在实现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中看到关键字实现的新nameof 。 或者甚至更好,如果可能的话,使用[CallerMemberName]作为Marc Gravell建议。

当具有自定义计算属性(例如在WPF中)没有自己的getter / setter时,使用nameof会很有用。

回答你的问题(试图找出优势):知道你的类型并等待特定属性改变的观察者有一个优势

 void Observe(Customer c) { c.PropertyChanged += (s, e) => { if (e.PropertyName == Customer.CustomerIdPropertyName) { MessageBox.Show("New id " + Customer.CustomerId); } } } 

如果你想进一步:

使用属性选择器表达式填充CustomerIdPropertyName可以避免键入错误。

您不需要使用nameof keyword(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字段的引用比在整个项目中搜索魔术字符串更容易)