仅重载相等运算符是不够的。在不同的情况下,可以调用以下所有命令:
object.Equals 和 object.GetHashCode
IEquatable<T>.Equals (可选,允许避免装箱)
operator ==和operator !=(可选,允许使用运算符)
覆盖时Equals,GetHashCode也必须覆盖。在实现时Equals,有许多特殊情况:与不同类型的对象进行比较,与自身进行比较等。
如果未覆盖,则Equals方法和==运算符对于类和结构的行为将有所不同。对于类,仅比较引用,而对于结构的属性值则通过反射进行比较,这会对性能产生负面影响。==除非被覆盖,否则不能用于比较结构。
通常,平等操作必须遵守以下规则:
绝对不能抛出异常。
自反性:A始终相等A(NULL某些系统中的值可能不正确)。
传递性:如果A等于B,B等于C,则A等于C。
如果A等于B,则A和B具有相等的哈希码。
继承树的独立性:ifB和C是Class2从继承的实例Class1:必须始终返回与调用相同的值。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); } }