C# C“覆盖等于使用”;作为「;以及针对正确性、灵活性和性能的专门方法
我想知道在C#中实现正确、灵活和快速的Equals的最佳方法,它几乎可以用于任何类和情况。我认为性能需要专门的Equals(将实际类的对象作为参数)。为了避免代码重复,一般Equals应该调用专门的Equals。空检查应该只执行一次,即使在继承的类中也是如此 我终于想出了这个设计:C# C“覆盖等于使用”;作为「;以及针对正确性、灵活性和性能的专门方法,c#,null,equals,code-duplication,C#,Null,Equals,Code Duplication,我想知道在C#中实现正确、灵活和快速的Equals的最佳方法,它几乎可以用于任何类和情况。我认为性能需要专门的Equals(将实际类的对象作为参数)。为了避免代码重复,一般Equals应该调用专门的Equals。空检查应该只执行一次,即使在继承的类中也是如此 我终于想出了这个设计: class MyClass { public Int32 SomeValue1 = 1; public Int32 SomeValue2 = 25; // Ignoring GetHash
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。错误的类类型将减少为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;
}
请参阅中的文档:“x.Equals(y)返回与y.Equals(x)相同的值。”
依靠重载给出不同的结果可能会导致可怕的问题,这对于调试来说是非常微妙的。我认为mc.Equals(mdc)和mdc.Equals(mc)在这里都返回true。虽然前者如我所料,但后者可能是设计中的一个实际的、巨大的错误。MyDerivedClass继承专门的Equals,即使它不应该等于任何MyClass。Jon,它应该是自反的吗?mdc可以包含比mc更多的属性,所以mdc可以不同于mc,但从mc的角度来看,它们可以是相等的。是的,它应该是绝对自反的。有关Object.Equals,请参阅文档。@mafurtct:你说得对:mdc.Equals(mc)将返回true。但是mdc.Equals((object)mc)将返回false。将更新答案。