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?

+5
source share
1 answer

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) .

+5
source

Source: https://habr.com/ru/post/1242169/


All Articles