What is the difference between IEqualityComparer and IEquatable?

前端 未结 5 1709
不思量自难忘°
不思量自难忘° 2020-11-30 19:45

I want to understand the scenarios where IEqualityComparer and IEquatable should be used. The MSDN documentation for both looks very similar.

5条回答
  •  无人及你
    2020-11-30 20:19

    You have already got the basic definition of what they are. In short, if you implement IEquatable on class T, the Equals method on an object of type T tells you if the object itself (the one being tested for equality) is equal to another instance of the same type T. Whereas, IEqualityComparer is for testing the equality of any two instances of T, typically outside the scope of the instances of T.

    As to what they are for can be confusing at first. From the definition it should be clear that hence IEquatable (defined in the class T itself) should be the de facto standard to represent uniqueness of its objects/instances. HashSet, Dictionary (considering GetHashCode is overridden as well), Contains on List etc make use of this. Implementing IEqualityComparer on T doesn't help the above mentioned general cases. Subsequently, there is little value for implementing IEquatable on any other class other than T. This:

    class MyClass : IEquatable
    

    rarely makes sense.

    On the other hand

    class T : IEquatable
    {
        //override ==, !=, GetHashCode and non generic Equals as well
    
        public bool Equals(T other)
        {
            //....
        }
    }
    

    is how it should be done.

    IEqualityComparer can be useful when you require a custom validation of equality, but not as a general rule. For instance, in a class of Person at some point you might require to test equality of two people based on their age. In that case you can do:

    class Person
    {
        public int Age;
    }
    
    class AgeEqualityTester : IEqualityComparer
    {
        public bool Equals(Person x, Person y)
        {
            return x.Age == y.Age;
        }
    
        public int GetHashCode(Person obj)
        {
            return obj.Age.GetHashCode;
        }
    }
    

    To test them, try

    var people = new Person[] { new Person { age = 23 } };
    Person p = new Person() { age = 23 };
    
    print people.Contains(p); //false;
    print people.Contains(p, new AgeEqualityTester()); //true
    

    Similarly IEqualityComparer on T doesn't make sense.

    class Person : IEqualityComparer
    

    True this works, but doesn't look good to eyes and defeats logic.

    Usually what you need is IEquatable. Also ideally you can have only one IEquatable while multiple IEqualityComparer is possible based on different criteria.

    The IEqualityComparer and IEquatable are exactly analogous to Comparer and IComparable which are used for comparison purposes rather than equating; a good thread here where I wrote the same answer :)

提交回复
热议问题