【C#】什么时候需要重写 Equals() 方法 & 如何重写 Equals() 方法

【C#】什么时候需要重写 Equals() 方法 & 如何重写 Equals() 方法

参考资料:How to: define value equality for a type (C# Programming Guide)


什么时候需要重写 Equals() 方法

引用类型

只有当需要修改该引用类型所定义的语义时,才应该重写实例版本的 Equals() 方法。如果类型需要采用值语义而不是引用语义(或者说,需要按照对象内容而不是对象身份来进行比较),那么就应该针对这个类型重写实例版本的 Object.Equals() 方法。

引用类型一般不需要重写 operator==()。

值类型

创建值类型的时候,总是应该针对这个类型重写 ValueType.Equals() 方法。
因为值类型都继承自 System.ValueType 类,System.ValueType 类默认通过反射来实现比较,效率不够高。

值类型中默认的 == 运算符会默认通过反射进行比较,因此,也应该重写 == 操作符。


重写 Equals() 方法时的注意事项

  • Equals() 方法必须满足等同关系的 3 项数学性质:自反性、对称性、可传递性。
  • Equals() 方法决不应该抛出异常。
  • 重写 Equals() 方法时,只有在基类型的 Equals(object) 不是由 System.ObjectSystem.ValueType 所提供的情况下,才需要调用基类型的版本。
  • 重写 Equals() 的时候,还应该让该类型实现 IEquatable<T> 接口。
  • 重写 Equals() 方法后,通常应该同时重写 GetHashCode() 方法。

重写 GetHashCode() 方法时的注意事项

  1. 如果 Equals() 方法认定两个对象相等,那么这两个对象的 HashCode 也必须相同;
  2. 对任意对象来说,其 HashCode 必须在生命周期内保持不变;
  3. HashCode 计算方法应该将其值均匀地映射到各个整数上,避免堆集。

一种常用的 HashCode 算法是:对类型中的每个相互独立的不可变字段调用 GetHashCode() 方法,并对返回的 HashCode 进行异或(XOR)运算,将得到的最终结果作为对象本身的 HashCode


示例代码

using System;

// 引用类型示例
public class ReferenceType : IEquatable<ReferenceType>
{
    public override bool Equals(object obj)
    {
        //return base.Equals(obj);
        return this.Equals(obj as ReferenceType);
    }

    public bool Equals(ReferenceType other)
    {
        if (object.ReferenceEquals(other, null))
            return false;

        if (object.ReferenceEquals(this, other))
            return true;

        if (this.GetType() != other.GetType())
            return false;

        // 根据具体的判断标准进行判断,此处省略
        throw new NotImplementedException();
    }
}

// 值类型示例
public struct ValueType : IEquatable<ValueType>
{
    public override bool Equals(object obj)
    {
        //return base.Equals(obj);

        if (obj is ValueType other)
        {
            return this.Equals(other);
        }

        return false;
    }

    public bool Equals(ValueType other)
    {
        // 根据具体的判断标准进行判断(例如比较每个成员值),此处省略
        throw new NotImplementedException();
    }

    public static bool operator ==(ValueType left, ValueType right)
    {
        return left.Equals(right);
    }

    public static bool operator !=(ValueType left, ValueType right)
    {
        return !(left.Equals(right));
    }
}
发布了76 篇原创文章 · 获赞 131 · 访问量 39万+

猜你喜欢

转载自blog.csdn.net/qq_21397217/article/details/99636385