为什么我不能在 IEqualityComparer<Customer> Equals 方法中使用 customer.Name.contains("smith")

Eli*_*eth 1 c# iequalitycomparer

我想使用 HashSet.Contains 方法,因为它超级快。

var hashset = new HashSet<Customer>(customers, new CustomerComparer());
var found = hashset.Contains(new Customer{ Id = "1234", Name = "mit" }); // "mit" instead of an equals "smith" in the comparer.
Run Code Online (Sandbox Code Playgroud)

我在客户对象上搜索多个属性。

我必须实现 IEqualityComparer 接口,如:

public class CustomerComparer : IEqualityComparer<Customer>
{
    public bool Equals(Customer x, Customer y)
    {
        return x.Id == y.Id && x.Name.Contains(y.Name);
    }      

    public int GetHashCode(Customer obj)
    {
        return obj.Id.GetHashCode() ^ obj.Name.GetHashCode();
    }
}
Run Code Online (Sandbox Code Playgroud)

当我不在 CustomerComparer Equals 方法中使用 Equals 方法(如 .Contains)时,为什么 Equals 方法永远不会命中?

Sef*_*efe 5

您实现相等比较器的方式无法正常工作。原因是散列集和相等比较器在内部是如何工作的。当 aDictionary或 aHashSet对项目进行比较时,它将首先调用GetHashCode这两个项目。只有当这些哈希码匹配时,它才会通过后续调用来确认完全匹配,Equals以避免在哈希码冲突的情况下出现错误匹配。如果您使用您的示例 (x.Name = "smith"y.Name = "mit"),该GetHashCode方法将为每个项目返回不同的哈希码,并且Equals永远不会被调用。

这种情况下的解决方案是仅使用Idfor 哈希码创建。这会稍微降低性能,因为您必须Equals更频繁地调用来解决冲突,但这是您必须付出的代价:

public int GetHashCode(Customer obj)
{
    return obj.Id.GetHashCode() ;
}
Run Code Online (Sandbox Code Playgroud)

您还应该考虑的是,您无法保证您现有的项目是xy。所以你必须Contains在两个方向使用:

public bool Equals(Customer x, Customer y)
{
    return x.Id == y.Id && (x.Name.Contains(y.Name) || y.Name.Contains(x.Name));
}      
Run Code Online (Sandbox Code Playgroud)