Overloading equality operators
suggest changeOverloading just equality operators is not enough. Under different circumstances, all of the following can be called:
object.Equals
andobject.GetHashCode
IEquatable<T>.Equals
(optional, allows avoiding boxing)operator ==
andoperator !=
(optional, allows using operators)
When overriding Equals
, GetHashCode
must also be overriden. When implementing Equals
, there are many special cases: comparing to objects of a different type, comparing to self etc.
When NOT overridden Equals
method and ==
operator behave differently for classes and structs. For classes just references are compared, and for structs values of properties are compared via reflection what can negatively affect performance. ==
can not be used for comparing structs unless it is overridden.
Generally equality operation must obey the following rules:
- Must not throw exceptions.
- Reflexivity:
A
always equalsA
(may not be true forNULL
values in some systems). - Transitvity: if
A
equalsB
, andB
equalsC
, thenA
equalsC
. - If
A
equalsB
, thenA
andB
have equal hash codes. - Inheritance tree independence: if
B
andC
are instances ofClass2
inherited fromClass1
:Class1.Equals(A,B)
must always return the same value as the call toClass2.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);
}
}
Found a mistake? Have a question or improvement idea?
Let me know.
Table Of Contents