C# 9 记录:ToHashSet() 没有产生预期的结果

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

通过这个测试,我曾希望 peopleHash 列表只有 3 条记录,但我得到了 4 条记录,因为相等性似乎包括非初始参数 location.

有没有办法获取我想要的 3 条记录的列表,其中只对初始属性执行比较并忽略其他位置参数?

像这样使用IEqualityComparer

using System;
using System.Collections.Generic;
using System.Linq;

public static class TestRecordTypes
{
    public static void Main()
    {
        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(new MyEqualityComparer());

        Console.WriteLine(peopleHash.Count());
    }        
}

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

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

class MyEqualityComparer : IEqualityComparer<Person>
{
    public bool Equals(Person p1, Person p2)
    {
        if (p1 == null && p2 == null)
           return true;
        else if (p1 == null || p2 == null)
           return false;
        else if(p1.FirstName == p2.FirstName && p1.LastName == p2.LastName)
                            
            return true;
        else
            return false;
    }

    public int GetHashCode(Person p)
    {
        string s = p.FirstName + p.LastName;
        return s.GetHashCode();
    }
}

您想更改 IEquatable<Person> 实现。为此,您可以在 record:

中添加 Equal 并覆盖 GetHashCode
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);
}

然后测试通过:

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