

#Equal definition how to
The following example shows how to implement value equality in a class (reference type). Starting in C# 9.0, you can use records to get value equality semantics without any unnecessary boilerplate code. Optional: To support definitions for "greater than" or "less than," implement the IComparable interface for your type, and also overload the = operators. Override Object.GetHashCode so that two objects that have value equality produce the same hash code. Optional but recommended: Overload the = and != operators.

For more information, see the class example later in this article. One strategy for making sure run-time types are always compared correctly is to implement IEquatable only in sealed classes. Also, make sure that the IEquatable implementation of the Equals method for the run-time type is used if the run-time and compile-time types of a variable are different.

Two variables should be deemed equal only if the run-time types of the variables being compared are the same. (Don't call base.Equals if the type inherits directly from Object, because the Object implementation of Object.Equals(Object) performs a reference equality check.) It should call base.Equals to examine fields that are in the base class. This method should examine only fields that are declared in the class. For classes that are related by inheritance: For example, you might decide to define equality by comparing only one or two fields in your type.

This is where the actual equivalence comparison is performed. Implement the System.IEquatable interface by providing a type-specific Equals method. In most cases, your implementation of bool Equals( object obj ) should just call into the type-specific Equals method that is the implementation of the System.IEquatable interface. Override the virtual Object.Equals(Object) method. However, both classes and structs require the same basic steps for implementing equality: The implementation details for value equality are different for classes and structs. Although this implementation produces correct results, it is relatively slow compared to a custom implementation that you write specifically for the type. This implementation uses reflection to examine all the fields and properties in the type. That breaks rules 1 or 2, depending on the argument to Equals.Īny struct that you define already has a default implementation of value equality that it inherits from the System.ValueType override of the Object.Equals(Object) method. However, x.Equals(y) throws an exception when x is null. Successive invocations of x.Equals(y) return the same value as long as the objects referenced by x and y aren't modified.Īny non-null value isn't equal to null. The transitive property: if (x.Equals(y) & y.Equals(z)) returns true, then x.Equals(z) returns true. The symmetric property: x.Equals(y) returns the same value as y.Equals(x). The reflexive property: x.Equals(x) returns true. In either case, and in both classes and structs, your implementation should follow the five guarantees of equivalence (for the following rules, assume that x, y and z are not null): You can base your definition of value equality on a comparison of all the fields and properties in the type, or you can base the definition on a subset. Typically, you implement value equality when you expect to add objects of the type to a collection, or when their primary purpose is to store a set of fields or properties. When you define a class or struct, you decide whether it makes sense to create a custom definition of value equality (or equivalence) for the type. Consider defining a record instead of a class when your type models data and should implement value equality. Records automatically implement value equality.
