Using string constant for notify property changed

拈花ヽ惹草 提交于 2019-12-01 11:26:00

Both versions are equally prone to typing errors.

If you have a somewhat recent version of .NET, your property changed handler should look like this:

protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
  var handler = this.PropertyChanged;
  if (handler != null)
  {
    handler(this, new PropertyChangedEventArgs(propertyName));
  }
}

Then your property looks like this:

private int _customerId;
public int CustomerId
{
    get
    {
         return _customerId;
    }
    set
    {
         if (_cusomterId != value)
         {
              _customerId = value;
              this.OnPropertyChanged();
         }
    }
}

And you don't have any trouble with typing errors.

There isn't an advantage compiler wise, since both will end up being a constant value.

I can't imagine a real advantage in using the code like that way. Either ways it is easy to make a typo, and you are not going to reuse that constant for anything, so it is pointless.

I had love to see the new nameof keyword implement in the next version of .NET. Or even better, if possible, use [CallerMemberName] as Marc Gravell suggested.

The use of nameof will be useful when having custom calculated properties (like in WPF for example) that don't have their own getter / setter.

To answer your question (trying to figure out the advantage) : there is an advantage for an observer who know your type and wait for a specific property to change

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

If you want to go futher :

Typing errors can be avoided using a property selector expression to fill your CustomerIdPropertyName.

You won't need it with nameof keyword (CTP). If you don't have this kind of observer, CalleMemberNameAttribute is the easiest way.

I imagine it is just to avoid bugs caused by typos and try and make the code a little easier to read. Also if you change the name of the property it means changing the value of the const will then work for all code that is checking if the property has changed. e.g. imagine this code:

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;
    }
}

In the example above, regardless of the value of the constant the code will work, and if you want to change the property name at some point then you only need to change the constant value and everything will still work with out having to find everywhere we are checking for the name (obviously if you want to change the name of the constant variable as well then you still need to find those references, but finding references to Public fields is easier than searching through the whole project for magic strings)

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!