【问题标题】:C# Overriding Equals using "as" and specialized Method for Correctness, Flexibility and PerformanceC# 使用“as”覆盖 Equals 和用于正确性、灵活性和性能的专用方法
【发布时间】:2009-01-20 11:10:07
【问题描述】:

我想知道在 C# 中实现 正确、灵活和快速的 Equals 的最佳方法,它几乎可以用于任何类和情况。我认为性能需要一个专门的 Equals(将实际类的对象作为参数)。为了避免代码重复,一般的 Equals 应该调用专门的 Equals。 Null 检查应该只执行一次,即使在继承的类中也是如此。

我终于想出了这个设计:


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 中进行排序。
  • 在某一点进行空值检查,即使是派生类也是如此。
  • 逐个检查属性提供了清晰的结构。

这个概念有缺陷,还是我错过了任何条件?

【问题讨论】:

    标签: c# null equals code-duplication


    【解决方案1】:

    当涉及不同类型时,您的 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) 相同的值。” 依靠重载给出不同的结果可能会导致可怕的问题,这些问题对于调试来说非常微妙。

    【讨论】:

    • 我认为 mc.Equals(mdc) 和 mdc.Equals(mc) 在这里都返回 true。虽然前者如我所料,但后者可能是设计中的一个实际的大错误。 MyDerivedClass 继承了专门的 Equals,即使它不应该等于任何 MyClass。
    • 乔恩,它应该是自反的吗? mdc 可以包含比 mc 更多的属性,因此 mdc 可以与 mc 不同,但从 mc 的角度来看,它们可以相等。
    • 是的,它应该绝对是反身的。请参阅 Object.Equals 的文档。
    • @mafutrct:你说得对:mdc.Equals(mc) 将返回 true。但是 mdc.Equals((object)mc) 将返回 false。将更新答案。
    猜你喜欢
    • 2012-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-11
    • 1970-01-01
    • 2023-04-09
    相关资源
    最近更新 更多