過載相等運算子

僅過載相等運算子是不夠的。在不同的情況下,可以呼叫以下所有內容:

  1. object.Equalsobject.GetHashCode
  2. IEquatable<T>.Equals(可選,允許避免拳擊)
  3. operator ==operator !=(可選,允許使用運算子)

當覆蓋 Equals 時,GetHashCode 也必須被覆蓋。在實現 Equals 時,有許多特殊情況:與不同型別的物件進行比較,與自我對比等。

當未覆蓋時 Equals 方法和 == 運算子對類和結構的行為不同。對於類,只比較引用,對於結構,通過反射比較屬性的值,這會對效能產生負面影響。== 不能用於比較結構,除非它被覆蓋。

通常,相等操作必須遵守以下規則:

  • 不得丟擲異常
  • 反身性:A 總是等於 A(某些系統中的 NULL 值可能不正確)。
  • Transitvity:如果 A 等於 BB 等於 C,則 A 等於 C
  • 如果 A 等於 B,則 AB 具有相同的雜湊碼。
  • 繼承樹獨立性:如果 BC 是從 Class1 繼承的 Class2 的例項:Class1.Equals(A,B) 必須始終返回與呼叫 Class2.Equals(A,B) 相同的值。
class Student : IEquatable<Student>
{
    public string Name { get; set; } = "";

    public bool Equals(Student other)
    {
        if (ReferenceEquals(other, null)) return false;
        if (ReferenceEquals(other, this)) return true;
        return string.Equals(Name, other.Name);
    }

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj)) return false;
        if (ReferenceEquals(this, obj)) return true;

        return Equals(obj as Student);
    }

    public override int GetHashCode()
    {
        return Name?.GetHashCode() ?? 0;
    }

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

    public static bool operator !=(Student left, Student right)
    {
        return !Equals(left, right);
    }
}