为什么.NET 的对象类中有两个重载?Equals
如果我想要一个自定义相等函数,例如以便我可以使用集合或字典,我应该覆盖两者(除了GetHashCode
),还是只覆盖其中一个就足够了。
3 回答
您不能覆盖静态版本。
使用静态版本的原因是您可以object.Equals(myObject, myOtherObject)
在不事先检查空值的情况下调用。
在内部,它只检查空值(true
如果两个对象都为空则返回),然后委托给myObject.Equals(myOtherObject)
. 因此,您只需要覆盖非静态 Equals 方法。
如果“第一个”对象为空,则存在静态方法。例如,如果a
为 nullb
且不为 null,则您将无法运行a.Equals(b)
,但您将能够运行object.Equals(a, b)
.
您应该(并且可以)仅覆盖实例方法,原因有两个。首先,您不能覆盖静态方法。其次,静态方法最终会调用非静态方法。
有关更多信息,请参阅文档。
您不能覆盖静态方法。
仅覆盖非静态方法就可以了...
阅读这篇文章: 如何:覆盖静态方法:
为什么我们不能覆盖静态成员?
真的,为什么?如果你仔细想想,这只是常识。覆盖普通(实例)成员使用虚拟调度机制将合同与实现分开。合约在编译时已知(实例成员签名),但实现仅在运行时已知(具体类型的对象提供具体实现)。您在编译时不知道实现的具体类型。
理解这一点很重要:当类型从其他类型继承时,它们履行一个共同的契约,而静态类型不受任何契约的约束(从纯 OOP 的角度来看)。语言中没有技术方法可以将两种静态类型与“继承”契约联系在一起。如果您要在两个不同的地方“覆盖” Log 方法,我们怎么知道我们在这里调用的是哪一个: Log.Message("what is the implementation?")
对于静态成员,您可以通过显式指定定义它们的类型来调用它们。这意味着,您可以直接调用实现,这同样不受任何合约的约束。
顺便说一句,这就是静态成员不能实现接口的原因。这就是虚拟调度在这里没有用的原因——所有客户端都直接调用实现,没有任何合同。