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); }