Home > database >  Automatically generating natural Equals and GetHashCode functions for objects
Automatically generating natural Equals and GetHashCode functions for objects

Time:02-22

I have found myself overriding the Equals and GetHashCode functions quite often when making classes. It seems like a waste of time since most of the time my Equals is just checking for the equality of every member (or iterating to check equality of IEnumerable elements). Similarly my GetHashCode is usually just the standard list of hash = hash * <prime> <sub-hash>, possibly iterated.

Is there a library to generate such natural Equals and GetHashCode functions? It seems possible using some of the meta-programming features of C#.

CodePudding user response:

Visual Studio 2019 and 2022 can generate these members for you.

To do that, right-click the class name and select Quick actions and refactorings... and then select Generate Equals and GetHashCode.

This displays a dialog where you choose the members that you want to contribute to the Equals and GetHashCode.

For example, given this class:

public sealed class TestClass
{
    public TestClass(int x, string y)
    {
        X = x;
        Y = y;
    }

    public int X { get; }
    public string Y { get; }
}

It will generate:

public sealed class TestClass : IEquatable<TestClass?>
{
    public TestClass(int x, string y)
    {
        X = x;
        Y = y;
    }

    public int X { get; }
    public string Y { get; }

    public override bool Equals(object? obj)
    {
        return Equals(obj as TestClass);
    }

    public bool Equals(TestClass? other)
    {
        return other != null &&
               X == other.X &&
               Y == other.Y;
    }

    public override int GetHashCode()
    {
        return HashCode.Combine(X, Y);
    }

    public static bool operator ==(TestClass? left, TestClass? right)
    {
        return EqualityComparer<TestClass>.Default.Equals(left, right);
    }

    public static bool operator !=(TestClass? left, TestClass? right)
    {
        return !(left == right);
    }
}

It's worth pointing out that for the sample class above, you can actually achieve the same result by using a record like so:

public sealed record TestClass(int X, string Y);

This will generate a GetHashCode() and Equals() using the X and Y properties of the record.

Given the record above, the following code:

TestClass t1 = new TestClass(1, "1");
TestClass t2 = new TestClass(1, "1");

Console.WriteLine(t1.GetHashCode());
Console.WriteLine(t2.GetHashCode());
Console.WriteLine(t1 == t2);

Outputs (on my computer):

-1671517974
-1671517974
True
  •  Tags:  
  • c#
  • Related