编译器选择错误的重载调用IEquatable <T> .Equals

Tom*_*m19 5 c# overloading iequatable

在性能敏感的程序中,我试图显式调用IEquatable<T>.Equals()而不是Object.Equals(在我的情况下避免装箱).尽管我付出了最大的努力,编译器总是选择Object.Equals()- 我不明白.一个人为的例子:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

同样可以设计的代码来证明这个问题:

// This calls IEquatable<Foo>
Foo f = new Foo();
f.Equals(f);

// This calls Object.Equals
IEquatable<Foo> i = new Foo();
i.Equals(i);
Run Code Online (Sandbox Code Playgroud)

此代码的输出是:

IEquatable.Equals
Object.Equals
Run Code Online (Sandbox Code Playgroud)

我阅读了Jon Skeet 关于重载文章,但仍然没有理解这里的问题.所以我的问题是,我如何明确调用IEquatable<Foo>.Equals上面的变量i

Sel*_*enç 5

选择的第二个重载与调用者类型无关的原因.相反,它与您传递给的参数类型相关Equals.所以,即使你打电话f.Equals(i),object.Equals也会选择方法.原因很简单,编译器寻找最合适的重载.因为IEquatable<Foo>不一定是必要的Foo,因为可能有另一种类型让我们说Bar哪种实现IEquatable<Foo>,在这种情况下,选择Equals(Foo f)重载是不正确的(或可能的).

由于编译器不检查基础类型IEquatable<Foo>,因此Foo如果要调用Equals(Foo)重载,则需要显式转换参数.