過載相等運算子
僅過載相等運算子是不夠的。在不同的情況下,可以呼叫以下所有內容:
object.Equals
和object.GetHashCode
IEquatable<T>.Equals
(可選,允許避免拳擊)operator ==
和operator !=
(可選,允許使用運算子)
當覆蓋 Equals
時,GetHashCode
也必須被覆蓋。在實現 Equals
時,有許多特殊情況:與不同型別的物件進行比較,與自我對比等。
當未覆蓋時 Equals
方法和 ==
運算子對類和結構的行為不同。對於類,只比較引用,對於結構,通過反射比較屬性的值,這會對效能產生負面影響。==
不能用於比較結構,除非它被覆蓋。
通常,相等操作必須遵守以下規則:
- 不得丟擲異常。
- 反身性:
A
總是等於A
(某些系統中的NULL
值可能不正確)。 - Transitvity:如果
A
等於B
,B
等於C
,則A
等於C
。 - 如果
A
等於B
,則A
和B
具有相同的雜湊碼。 - 繼承樹獨立性:如果
B
和C
是從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);
}
}