Search code examples
c#wpfequalsiequatable

Equals override vs. IEquatable<>


For the life of me, I can't get my WPF binding to work correctly for a RibbonComboBox's SelectedItem property.

Then I started reading about how .NET compares items. My understanding is that, in some cases, it compares the actual pointer. In which case, loading a new and equal value from a database, for example, it may not be considered equal.

So then I started looking into explicitly implementing Equals for my type. However, this seems a bit confusing as there are at least two different versions I can implement.

The code below shows I can either override object.Equals, or I can implement IEquatable<>. In fact, the code below implements both, and testing indicates that both are called.

public class TextValuePair : IEquatable<TextValuePair>
{
    public string Text { get; set; }
    public int Value { get; set; }

    public override bool Equals(object obj)
    {
        if (obj == null || !(obj is TextValuePair))
            return false;
        return Value == (obj as TextValuePair).Value;
    }

    public override int GetHashCode()
    {
        return Value;
    }

    public bool Equals(TextValuePair obj)
    {
        Debug.Assert(obj != null);
        if (obj == null)
            return false;
        return Value == obj.Value;
    }
}

Can someone help me understand what is required to avoid my objects from being compared for equivalence by .NET library routines according to pointers having the same value? Is it really necessary to implement both versions of Equals?


Solution

  • As pointed by msdn, if you are implementing IEquatable<T> you will still need to override Equals because it will still be called with the signature Equals(System.Object, System.Object) and yhe override should be consistent with the methods implemented from IEquatable<T>.

    Also as in the question about the difference between iequatable and just overriding object equals which Arno showed in the comment, IEquatable<T> is used when operations on collections are required to optimize them, not to need the boxing anymore, and instead call the direct Equals with the specific type.

    You have two options:

    If you are interested in performance when you are working with collections in your program, you could keep implementing the both Equals methods;

    or

    You could just remove the IEquatable<T> and only override Equals to simplify your code.

    Additionally, whenever you override Equals, you should also always override GetHashCode as well.