具有自定义 EqualityComparer 的 C# Hashset.Contains 从不调用 GetHashCode()

C# Hashset.Contains with custom EqualityComparer never calls GetHashCode()

我的数据库中有一个非常大(数十万)的客户对象哈希集。然后我得到一个新导入的客户对象哈希集,并且必须检查每个新对象是否包含在现有哈希集中。性能很重要。

我不能使用默认的 Equalitycomparer,因为它只需要根据三个属性进行比较。此外,由于其他原因,我无法覆盖 Customer class 的 Equals 和 GetHashCode 函数。所以我的目标是自定义 EqualityComparer(我尝试实现 IEqualityComparer 或从 EqualityComparer 继承并覆盖,如下所示 - 两者都具有相同的最终结果)。

public class CustomerComparer : EqualityComparer<Customer>
    {
        public CustomerComparer(){ }

        public override bool Equals(Customer x, Customer y)
        {
            return x != null &&
                   y != null &&
                   x.Name == y.Name &&
                   x.Description == y.Description &&
                   x.AdditionalInfo == y.AdditionalInfo
        }

        public override int GetHashCode(Customer obj)
        {
            var hashCode = -1885141022;
            hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(obj.Name);
            hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(obj.Description);
            hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(obj.AdditionalInfo);
            return hashCode;
        }
    }

现在我的问题是:当我使用默认的 EqualityComparer 时,通常只调用 Customer 的 GetHashCode 方法,并且我的用例的性能非常好(1-2 秒)。当我使用自定义 EqualityComparer 时,从未调用 GetHashCode 方法,但始终调用 Equals 方法。我的用例的性能非常糟糕(数小时)。请参阅下面的代码:

public void FilterImportedCustomers(ISet<Customer> dataBase, IEnumerable<Customer> imported){

    var equalityComparer = new CustomerComparer();
    foreach (var obj in imported){
        
        //great performance, always calls Customer.GetHashCode
        if (!dataBase.Contains(obj){
        //...
        }

        //awful performance, only calls CustomerComparer.AreEqual
        if (!dataBase.Contains(obj, equalityComparer))
        //...
        }            
    }
}

有没有人知道我该如何解决这个问题?那太棒了,我真的一直在努力解决这个巨大的性能问题。

编辑:

我在初始化哈希集时通过我的 EuqalityComparer 解决了这个问题!通过使用采用 IEqualityComparer 的构造函数重载,因此 var database = new HashSet(new CustomerComparer())

谢谢大家!

我在初始化哈希集时通过传递我的 EqualityComparer 解决了这个问题!使用了采用 IEqualityComparer 的构造函数重载,因此 var database = new HashSet(new CustomerComparer())

感谢Lee和NetMage在我的原创下发表评论post。