简体   繁体   中英

C#/WinForms/INotifyPropertyChanged: Elegant way to check for equality when either or both operands might be null

I have a class Bar that implements INotifyPropertyChanged. When setting the property CurrentFoo, I want to raise PropertyChanged if the value is changing. Foo implements IEquatable but not the == operator.

Currently my code looks like this:

public class Bar : INotifyPropertyChanged
{
    // ...

    private Foo fooValue;

    /// <summary>
    /// Gets or sets the active Foo
    /// </summary>
    /// <value>The active Foo.</value>
    public Foo CurrentFoo
    {
        get
        {
            return this.fooValue;
        }

        set
        {
            // Notify listeners if value is changing.
            if (null == this.fooValue && null != value
                || null != this.fooValue && null == value
                || null != this.fooValue && null != value && !this.fooValue.Equals(value))
            {
                this.fooValue = value;
                this.OnPropertyChanged("CurrentFoo");
            }
        }
    }

   // ...
}

And it woks, but...ugleh! Is there a more elegant/best-practices way of doing this check without restoring to the Null object pattern (inconsistent with the rest of our codebase)?

I've considered writing a utility method like IsOneObjectNullButNotBoth(object a, object b)...but again, blah. Surely I'm missing a handy-dandy class library method, though I already checked those.

Testing one of the values for null is enough, because the Equals method should return false if the argument is null:

if ((this.fooValue != value) ||
    (this.fooValue != null && !this.fooValue.Equals(value)))
{
    this.fooValue = value;
    this.OnPropertyChanged("CurrentFoo");
}

Alternatively, you can use the default EqualityComparer for Foo which checks for nulls and calls the Equals method:

if (!EqualityComparer<Foo>.Default.Equals(this.FooValue, value))
{
    this.fooValue = value;
    this.OnPropertyChanged("CurrentFoo");
}

It seems like you could use an extension method here:

    if(fooValue.IsChanged(value))
    {
    }
    static public class Ext {
      static public bool IsChanged(this Foo fooValue, Foo value) {
        return null == fooValue && null != value 
          || null != this.fooValue 
          && null == value 
          || null != this.fooValue 
          && null != value 
          && !this.fooValue.Equals(value));
       }
    }

This is built into the .net framework and will do just this

if (!System.Collections.Generic.EqualityComparer<Foo>.Default.Equals(value, fooValue))
{
    // value changed logic here.
}

Well, may be this way:

Should work.

    public Foo CurrentFoo
    {
        get
        {
            return this.fooValue;
        }

        set
        {
            // Notify listeners if value is changing.
            bool bok = false;
            if (this.fooValue !=null && !this.fooValue.Equals(value))
                bok = true;
            else if(this.fooValue ==null)
                 bok = (this.fooValue == value);
            if(bok) {
                this.fooValue = value;
                this.OnPropertyChanged("CurrentFoo");
            }
        }
    }

This is how I would write it if I didn't want to use EqualityComparer :

if ((obj1 ?? obj2) != null && (obj1 == null || !obj1.Equals(obj2)))
{
    // objects are diffrent
}

I think that's about as elegant as I can make it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM