C# 9 record: ToHashSet() not producing the desired result

public static class TestRecordTypes
{
    public static void RunTest()
    {
        List<Person> people = new List<Person>()
        {
            new Person("John", "Doe", "home"),
            new Person("John", "Doe", "Away"),
            new Person("Billy", "Doe", "home"),
            new Person("Billy", "Doe", "home"),
            new Person("Batty", "Bo", "home"),
        };

        var peopleHash = people.ToHashSet();

        Debug.WriteLine($"{peopleHash}");
    }        
}

public record Person(string FirstName, string LastName)
{
    string _location;

    public Person(string firstName, string lastName, string location):
        this(firstName, lastName)
    {
        _location = location;
    }
}

With this test I had hoped that peopleHash list would only have 3 records, but I get 4 as the equality appears to be including the non init parameter location.

Is there a way to get the list of 3 records I want where the comparison is performed on the init properties only and ignores the additional location parameter?

Answer

You want to change the IEquatable<Person> implementation. For that, you can add Equal and override GetHashCode in the record:

public record Person(string FirstName, string LastName)
{
    string _location;

    public Person(string firstName, string lastName, string location) :
        this(firstName, lastName) => _location = location;

    public virtual bool Equals(Person other)
    {
        if (ReferenceEquals(null, other)) return false;
        if (ReferenceEquals(this, other)) return true;
        return FirstName == other.FirstName && LastName == other.LastName;
    }

    public override int GetHashCode() => HashCode.Combine(FirstName, LastName);
}

then the test passes:

[TestMethod]
public void HashTest()
{
    List<Person> people = new List<Person>()
    {
        new ("John", "Doe", "home"),
        new ("John", "Doe", "Away"),
        new ("Billy", "Doe", "home"),
        new ("Billy", "Doe", "home"),
        new ("Batty", "Bo", "home"),
    };

    var peopleHash = people.ToHashSet();
    Assert.AreEqual(3, peopleHash.Count);
}

Leave a Reply

Your email address will not be published. Required fields are marked *