Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/272.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# C“覆盖等于使用”;作为「;以及针对正确性、灵活性和性能的专门方法_C#_Null_Equals_Code Duplication - Fatal编程技术网

C# C“覆盖等于使用”;作为「;以及针对正确性、灵活性和性能的专门方法

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

我想知道在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。错误的类类型将减少为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。将更新答案。