代码之家  ›  专栏  ›  技术社区  ›  Eddie Velasquez

对于引用类型,Equals()的“最佳”规范实现是什么?

  •  6
  • Eddie Velasquez  · 技术社区  · 16 年前

    为引用类型实现Equals()比看起来要困难。我目前的规范实现是这样的:

    public bool Equals( MyClass obj )
    {
      // If both refer to the same reference they are equal.
      if( ReferenceEquals( obj, this ) )
        return true;
    
      // If the other object is null they are not equal because in C# this cannot be null.
      if( ReferenceEquals( obj, null ) )
       return false;
    
       // Compare data to evaluate equality    
       return _data.Equals( obj._data );
    }
    
    public override bool Equals( object obj )
    {
      // If both refer to the same reference they are equal.
      if( ReferenceEquals( obj, this ) )
        return true;
    
      // If the other object is null or is of a different types the objects are not equal. 
      if( ReferenceEquals( obj, null ) || obj.GetType() != GetType() )
        return false;
    
      // Use type-safe equality comparison
      return Equals( (MyClass)obj );
    }
    
    public override int GetHashCode()
    {
      // Use data's hash code as our hashcode  
      return _data.GetHashCode();
    }
    

    我认为这涵盖了所有角落(继承等)的情况,但我可能错了。你们觉得呢?

    6 回复  |  直到 16 年前
        1
  •  4
  •   cori    13 年前

    不久前,我为此写了一本相当全面的指南。首先,你的equals实现应该是共享的(即,接受对象的重载应该传递给接受强类型对象的重载)。此外,您需要考虑一些事情,例如您的对象应该是不可变的,因为需要重写GetHashCode。更多信息请点击此处:

    http://gregbeech.com/blog/implementing-object-equality-in-dotnet

        2
  •  1
  •   tvanfosson    16 年前

    最好希望如此。_如果数据也是引用类型,则它不是null。

    public bool Equals( MyClass obj )
    {
        if (obj == null) {
            return false;
        }
        else {
            return (this._data != null && this._data.Equals( obj._data ))
                             || obj._data == null;
        }
    }
    
    public override bool Equals( object obj )
    {
        if (obj == null || !(obj is MyClass)) {
            return false;
        }
        else {
            return this.Equals( (MyClass)obj );
        }
    }
    
    public override int GetHashCode() {
        return this._data == null ? 0 : this._data.GetHashCode();
    }
    
        3
  •  0
  •   chakrit Dutchie432    16 年前

    关于继承,我认为你应该让OO范式发挥它的魔力。

    具体而言 GetType() 应该删除检查,它可能会破坏多态性。

        4
  •  0
  •   Santiago Palladino    16 年前

    我同意chakrit的观点,如果不同类型的对象具有相同的数据或ID,则应允许它们在语义上相等。

    就我个人而言,我使用以下方法:

        public override bool Equals(object obj)
        {
            var other = obj as MyClass;
            if (other == null) return false;
    
            return this.data.Equals(other.data);
        }
    
        5
  •  0
  •   JimmyPena Alex K.    13 年前

    这取决于你写的是值类型还是引用类型。对于可排序的值类型,我建议如下: A code snippet for Visual Studio 2005 that implements a skeleton value type adhering to Framework Design Guidelines

        6
  •  0
  •   Manfred    3 年前

    由于Greg Beech接受的答案中的链接已断开,我希望这个答案可能对一些人有所帮助。

    Microsoft的文档提供了以下示例,用于典型实现 Equals() 关于参考类型(即类):

    public override bool Equals(object obj) => this.Equals(obj as TwoDPoint);
    
    public bool Equals(TwoDPoint p)
    {
       if (p is null)
       {
             return false;
       }
    
       // Optimization for a common success case.
       if (Object.ReferenceEquals(this, p))
       {
             return true;
       }
    
       // If run-time types are not exactly the same, return false.
       if (this.GetType() != p.GetType())
       {
             return false;
       }
    
       // Return true if the fields match.
       // Note that the base class is not invoked because it is
       // System.Object, which defines Equals as reference equality.
       return (X == p.X) && (Y == p.Y);
    }
    

    可以在以下位置找到完整的示例,其中包含更多详细信息,包括在派生类或结构中做什么 "How to define value equality for a class or struct (C# Programming Guide)"

    作为微软文档中描述的替代方案,该方法 GetHashCode() 也可以按如下方式实现:

    public override int GetHashCode()
    {
       return HashCode.Combine(X, Y);
    }