The compiler chooses the wrong overload causing IEquatable <T> .Equals
In a performance-sensitive program, I'm trying to explicitly call IEquatable<T>.Equals() , not Object.Equals (to avoid boxing in my case). Despite all my efforts, the compiler always selects Object.Equals() instead, which I don't understand. A contrived example class:
class Foo : IEquatable<Foo> { public bool Equals(Foo f) { Console.WriteLine("IEquatable.Equals"); return true; } public override bool Equals(object f) { Console.WriteLine("Object.Equals"); return true; } } Similarly contrived code demonstrating the problem:
// This calls IEquatable<Foo> Foo f = new Foo(); f.Equals(f); // This calls Object.Equals IEquatable<Foo> i = new Foo(); i.Equals(i); The output of this code is:
IEquatable.Equals Object.Equals I read Jon Skeet 's article on congestion and left, still not understanding the problem here. So my question is: how can I explicitly call IEquatable<Foo>.Equals on variable i above?
The reason the second selected congestion is not related to the type of caller. Rather, it refers to the type of argument you pass to Equals . Therefore, even if you call f.Equals(i) , the object.Equals method will be selected. The reason is simple, the compiler is looking for the most suitable overload. Since IEquatable<Foo> does not have to be Foo , another type of let say Bar may appear that implements IEquatable<Foo> , in which case it would be wrong (or possible) to select Equals(Foo f) overloads.
Since the compiler does not check the base type of IEquatable<Foo> , you need to explicitly specify the parameter in Foo if you want to overload Equals(Foo) .