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

时间:2014-08-22 12:55:03

标签: c# wpf inotifypropertychanged

我正在使用一些现有代码并试图找出在实现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");
         }
    }
}

4 个答案:

答案 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字段的引用比在整个项目中搜索魔术字符串更容易)