【问题标题】:Correct way to override Equals(object obj) when dealing with sub/superclasses?处理子/超类时覆盖 Equals(object obj) 的正确方法?
【发布时间】:2012-10-11 12:06:42
【问题描述】:

我正在使用以下代码来测试 Equals

public override bool Equals(object obj)
{
    // Equals must return false on compares to null. 
    if (obj == null || GetType() != obj.GetType())
        return false;

    Foo fooItem = obj as Foo;

    return fooItem.FooId == this.FooId;
}

如果 obj 是一个超类,我应该如何处理它?它应该总是返回假,还是有时它应该是真的?

如何进行比较?

【问题讨论】:

    标签: c# .net superclass gethashcode iequalitycomparer


    【解决方案1】:

    这真的取决于你想要平等的含义。

    我认为我从来没有允许不同班级之间的平等。不过,您可能有一个案例。

    请记住,您可以使用自定义 IEqualityComparer<T>。每当您想以一种并非真正通用的方式测试相等性时,这是一个很好的策略,因为这意味着其他情况下的其他代码不会被您的覆盖所困扰。每种类型只能覆盖一次 Equals,但可以拥有任意数量的比较器。

    【讨论】:

      【解决方案2】:

      只需摆脱 GetType() 比较并将 obj as Foo 移动到第一行。

      代码将是

      public override bool Equals(object obj)
      {
          var fooItem = obj as Foo;
          // Equals must return false on compares to null. 
          if (obj == null) {
              return false;
          }
      
          return fooItem.FooId == this.FooId;
      }
      

      这假设所有 Foo 甚至派生一次都有意义的全值比较,或者实现上述 Equals 覆盖的类是密封的。

      如果对所有 Foo(包括派生一次)没有有意义的值比较,那么我建议改用 IEqualityComaprer。与所有其他实例方法一样,只有当它们确实是类型的一部分而不仅仅是辅助方法时,您才应该将它们包含在类层次结构中

      【讨论】:

        【解决方案3】:

        虽然在某些情况下,让不同类型的对象报告自己彼此相等可能很有用,但我强烈建议不要这样使用;我唯一能认为这是合理的情况是,如果所有类型都继承自一个公共基类,其中包括使用各种虚拟方法的密封Equals 方法,询问对象它们支持的加速相等比较的方法,使用最佳可用方法,如果没有可用的加速方法,则将对象转换为规范形式并进行比较。

        例如,考虑抽象的ImmutableFloatingPointMatrix 类型,它实现了一个双参数索引属性获取器。如果两个矩阵具有相同的大小并且在相同的位置具有相同的值,则它们应该被认为是相等的。虽然派生类可以使用二维数组来保存矩阵的内容,但也可以使用许多其他存储方法。例如,可能有一个具体的IdentityMatrix 类,它有一个Size 字段,总是将它的维度报告为SizexSize,并且有一个索引属性,它为主对角线上的单元格返回 1.0 和 0.0别处。也可以有一个DiagonalMatrix,它使用一个Size-item 数组来保存对角线上的东西。虽然可以通过检查所有相应的元素来比较任何两个矩阵的相等性,例如检查DiagonalMatrixIdentitymMatrix 可以通过确保两个矩阵大小相同并且数组中的所有项目都等于 1.0 来更好地处理(不必费心检查主对角线之外的任何点,因为不会有任意)。

        即使对于 Equals 的语义可以合理定义的类型,以便不同类型的对象将自己报告为相等,这也可能不是最好的主意。在可以使用自定义EqualityComparer 的情况下,这可能比Equals 的奇怪覆盖更好。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2013-05-16
          • 2016-07-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-03-08
          • 2013-08-09
          相关资源
          最近更新 更多