Implementing INotifyPropertyChanged - does a better way exist?

前端 未结 30 2674
感情败类
感情败类 2020-11-21 05:23

Microsoft should have implemented something snappy for INotifyPropertyChanged, like in the automatic properties, just specify {get; set; notify;} I

30条回答
  •  情话喂你
    2020-11-21 05:40

    I realize this question already has a gazillion answers, but none of them felt quite right for me. My issue is I don't want any performance hits and am willing to put up with a little verbosity for that reason alone. I also don't care too much for auto properties either, which led me to the following solution:

    public abstract class AbstractObject : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
    
        public void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    
        protected virtual bool SetValue(ref TKind Source, TKind NewValue, params string[] Notify)
        {
            //Set value if the new value is different from the old
            if (!Source.Equals(NewValue))
            {
                Source = NewValue;
    
                //Notify all applicable properties
                foreach (var i in Notify)
                    OnPropertyChanged(i);
    
                return true;
            }
    
            return false;
        }
    
        public AbstractObject()
        {
        }
    }
    

    In other words, the above solution is convenient if you don't mind doing this:

    public class SomeObject : AbstractObject
    {
        public string AnotherProperty
        {
            get
            {
                return someProperty ? "Car" : "Plane";
            }
        }
    
        bool someProperty = false;
        public bool SomeProperty
        {
            get
            {
                return someProperty;
            }
            set
            {
                SetValue(ref someProperty, value, "SomeProperty", "AnotherProperty");
            }
        }
    
        public SomeObject() : base()
        {
        }
    }
    

    Pros

    • No reflection
    • Only notifies if old value != new value
    • Notify multiple properties at once

    Cons

    • No auto properties (you can add support for both, though!)
    • Some verbosity
    • Boxing (small performance hit?)

    Alas, it is still better than doing this,

    set
    {
        if (!someProperty.Equals(value))
        {
            someProperty = value;
            OnPropertyChanged("SomeProperty");
            OnPropertyChanged("AnotherProperty");
        }
    }
    

    For every single property, which becomes a nightmare with the additional verbosity ;-(

    Note, I do not claim this solution is better performance-wise compared to the others, just that it is a viable solution for those who don't like the other solutions presented.

提交回复
热议问题