我想知道在C#中实现正确,灵活和快速Equals的最佳方法,几乎可以用于任何类和情况.我认为性能需要专门的Equals(将实际类的对象作为参数).为了避免代码重复,一般Equals应该调用专门的Equals.即使在继承的类中,也应该只执行一次空检查.
我终于想出了这个设计:
class MyClass { public Int32 SomeValue1 = 1; public Int32 SomeValue2 = 25; // Ignoring GetHashCode for simplicity. public override bool Equals(object obj) { return Equals (obj as MyClass); } public bool Equals(MyClass obj) { if (obj == null) { return false; } if (!SomeValue1.Equals (obj.SomeValue1)) { return false; } if (!SomeValue2.Equals (obj.SomeValue2)) { return false; } return true; } } class MyDerivedClass : MyClass { public Int32 YetAnotherValue = 2; public override bool Equals(object obj) { return Equals (obj as MyDerivedClass); } public bool Equals(MyDerivedClass obj) { if (!base.Equals (obj)) { return false; } if (!YetAnotherValue.Equals (obj.YetAnotherValue)) { return false; } return true; } }
重要的想法:
使用"as"运算符.这样我们就不必检查一般Equals中的空值.错误的类类型将减少为null,并将在专门的Equals中进行排序.
即使对于派生类,也只需要检查一个点.
逐个检查属性提供了清晰的结构.
这个概念有缺陷,还是我错过了任何条件?
当涉及不同类型时,您的Equals方法不具有反身性:
MyDerivedClass mdc = new MyDerivedClass(); MyClass mc = new MyClass(); Object omdc = mdc; Object omc = mc; // mc.Equals(mdc) - true // mdc.Equals(mc) - true by calling the right overload // omc.Equals(omdc) - true // omdc.Equals(omc) - false, the "as" in MyDerivedClass will result in null
通常的方法是使用:
if (GetType() != other.GetType()) { return false; }
请参阅Object.Equals中的文档:"x.Equals(y)返回与y.Equals(x)相同的值." 依靠重载来提供不同的结果可能最终会出现可怕的问题,这些问题对调试来说非常微妙.