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

时间:2020-03-05 18:56:32  来源:igfitidea点击:

为引用类型实现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();
}

我认为这涵盖了所有极端情况(继承性等),但我可能是错的。你们有什么感想?

解决方案

回答

这取决于我们要编写的是值类型还是引用类型。对于可排序的值类型,我建议这样做:
Visual Studio 2005的代码段,该代码段实现了遵循框架设计准则的框架值类型

回答

关于继承,我认为我们应该让OO范式发挥其魔力。

具体来说,应该删除" GetType()"检查,这可能会破坏多态性。

回答

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

我个人使用以下方法:

public override bool Equals(object obj)
    {
        var other = obj as MyClass;
        if (other == null) return false;

        return this.data.Equals(other.data);
    }

回答

最好希望this._data也是引用类型,也不为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();
}

回答

不久前,我为此写了一篇相当全面的指南。首先,应该共享equals的实现(即,采用对象的重载应传递给采用强类型对象的重载)。另外,由于需要覆盖GetHashCode,因此我们需要考虑诸如对象之类的东西是不可变的。更多信息在这里:

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