I want to understand the scenarios where IEqualityComparer
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 :)