编译器选择错误的重载调用 IEquatable<T>.Equals
Compiler picking wrong overload calling IEquatable<T>.Equals
在性能敏感的程序中,我试图显式调用 IEquatable<T>.Equals()
而不是 Object.Equals
(以避免在我的情况下装箱)。尽管我尽了最大的努力,编译器总是选择 Object.Equals()
而不是 - 我不明白。一个人为的例子 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;
}
}
演示问题的同样设计的代码:
// This calls IEquatable<Foo>
Foo f = new Foo();
f.Equals(f);
// This calls Object.Equals
IEquatable<Foo> i = new Foo();
i.Equals(i);
这段代码的输出是:
IEquatable.Equals
Object.Equals
我读了 Jon Skeet 的 article on overloading 并且离开时仍然不明白这里的问题。所以我的问题是,如何在上面的变量 i
上显式调用 IEquatable<Foo>.Equals
?
选择第二个重载的原因与调用者的类型无关。相反,它与您传递给 Equals
的参数类型有关。因此,即使您调用 f.Equals(i)
,也会选择 object.Equals
方法。原因很简单,编译器寻找最合适的重载。由于 IEquatable<Foo>
不一定是 Foo
,因为可能还有另一种类型 Bar
实现了 IEquatable<Foo>
,在这种情况下它是不正确的(或可能)选择 Equals(Foo f)
重载。
由于编译器不检查IEquatable<Foo>
的底层类型,如果你想调用Equals(Foo)
重载,你需要显式地将参数转换为Foo
。
在性能敏感的程序中,我试图显式调用 IEquatable<T>.Equals()
而不是 Object.Equals
(以避免在我的情况下装箱)。尽管我尽了最大的努力,编译器总是选择 Object.Equals()
而不是 - 我不明白。一个人为的例子 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;
}
}
演示问题的同样设计的代码:
// This calls IEquatable<Foo>
Foo f = new Foo();
f.Equals(f);
// This calls Object.Equals
IEquatable<Foo> i = new Foo();
i.Equals(i);
这段代码的输出是:
IEquatable.Equals
Object.Equals
我读了 Jon Skeet 的 article on overloading 并且离开时仍然不明白这里的问题。所以我的问题是,如何在上面的变量 i
上显式调用 IEquatable<Foo>.Equals
?
选择第二个重载的原因与调用者的类型无关。相反,它与您传递给 Equals
的参数类型有关。因此,即使您调用 f.Equals(i)
,也会选择 object.Equals
方法。原因很简单,编译器寻找最合适的重载。由于 IEquatable<Foo>
不一定是 Foo
,因为可能还有另一种类型 Bar
实现了 IEquatable<Foo>
,在这种情况下它是不正确的(或可能)选择 Equals(Foo f)
重载。
由于编译器不检查IEquatable<Foo>
的底层类型,如果你想调用Equals(Foo)
重载,你需要显式地将参数转换为Foo
。