Show / Hide Table of Contents

Autogenerated GetHashCode/Equals

Visual Studio IDE can help to generate Equals and GetHashCode overrides instead of hand-written implementation. This way has several flaws:

  • Developer can add a new field into the class and forget to take it into account inside of Equals and GetHashCode
  • The result of GetHashCode can be the same between application restarts
  • A lot of fields declared in the targer class decrese readability of these methods
  • If one or more fields have custom struct type then you should implement equality/inequality operators for such struct as well as GetHashCode and Equals recursively

EqualityComparerBuilder<T> is a way to fix these inconveniences. All you need is to call appropriate builder method in this class and obtains the necessary implementation.

The following example demonstrates recommended usage of this class:

using DotNext;

public class Person: IEquatable<Person>
{
    private static readonly Func<Person, Person, bool> equals;
    private static readonly Func<Person, int> hashCode;

    static Person() => new EqualityComparerBuilder<Person>().Build(out equals, out hashCode);

    public string FirstName { get; set; }
    public string SecondName { get; set; }
    public byte Age { get; set; }

    public override int GetHashCode() => hashCode(this);
    public bool Equals(Person other) => equals(this, other);
    public override bool Equals(object other) => Equals(other as Person);
}

Constructed methods rely on the instance fields (public and private) declared in the specified class and its ancestors. But some fields can be excluded from the generated code using ExcludedFields property.

Important

It is not recommended to call builder method multiple times with the same generic argument. Code generation process is expensive and may affect performance of your application. The recommended approach is to cache generated methods. Additionally, generated code inside of these methods don't provide nullability check of the first passed argument because expected behavior is a passing of this parameter.

Automatically generated implementation of equality check follows certain rules:

  • If field is of reference type then equality comparison between two values of the field based on Object.Equals method
  • If field is of value type then equality comparison between two values of the field based on bitwise equality provided by BitwiseComparer<T> class.
  • Simple equality check is performed for field of primitive or pointer type
  • OneDimensionalArray is performed for field of array type whose elements are of value type
  • Enumerable.SequenceEqual is used to compare elements in the array if field has array type whose elements are of reference type.

Automatically generated implementation of hash code function follows the similar rules:

  • For field of primite type, conversion to int is performed
  • Object.GetHashCode is used for field of reference type
  • Bitwise hash code located in BitwiseComparer<T> class is performed for field of value type
  • Bitwise hash code located in OneDimensionalArray class is performed for field of array type whose elements are of value type
  • Sequence hash code located in Sequence class is performed for field of array type whose elements are of reference type
  • Improve this Doc
☀
☾
Back to top Generated by DocFX