2

为什么.NET 的对象类中有两个重载?Equals如果我想要一个自定义相等函数,例如以便我可以使用集合或字典,我应该覆盖两者(除了GetHashCode),还是只覆盖其中一个就足够了。

4

3 回答 3

9

您不能覆盖静态版本。

使用静态版本的原因是您可以object.Equals(myObject, myOtherObject)在不事先检查空值的情况下调用。

在内部,它只检查空值(true如果两个对象都为空则返回),然后委托给myObject.Equals(myOtherObject). 因此,您只需要覆盖非静态 Equals 方法。

于 2013-02-12T15:42:27.253 回答
2

如果“第一个”对象为空,则存在静态方法。例如,如果a为 nullb且不为 null,则您将无法运行a.Equals(b),但您将能够运行object.Equals(a, b).

您应该(并且可以)仅覆盖实例方法,原因有两个。首先,您不能覆盖静态方法。其次,静态方法最终会调用非静态方法。

有关更多信息,请参阅文档

于 2013-02-12T15:42:37.950 回答
2

您不能覆盖静态方法。

仅覆盖非静态方法就可以了...

阅读这篇文章: 如何:覆盖静态方法

为什么我们不能覆盖静态成员?

真的,为什么?如果你仔细想想,这只是常识。覆盖普通(实例)成员使用虚拟调度机制将合同与实现分开。合约在编译时已知(实例成员签名),但实现仅在运行时已知(具体类型的对象提供具体实现)。您在编译时不知道实现的具体类型。

理解这一点很重要:当类型从其他类型继承时,它们履行一个共同的契约,而静态类型不受任何契约的约束(从纯 OOP 的角度来看)。语言中没有技术方法可以将两种静态类型与“继承”契约联系在一起。如果您要在两个不同的地方“覆盖” Log 方法,我们怎么知道我们在这里调用的是哪一个: Log.Message("what is the implementation?")

对于静态成员,您可以通过显式指定定义它们的类型来调用它们。这意味着,您可以直接调用实现,这同样不受任何合约的约束。

顺便说一句,这就是静态成员不能实现接口的原因。这就是虚拟调度在这里没有用的原因——所有客户端都直接调用实现,没有任何合同。

于 2013-02-12T15:41:30.657 回答