简体   繁体   English

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

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

I have a very large (hundreds of thousands) hashset of Customer objects in my database.我的数据库中有一个非常大(数十万)的客户对象哈希集。 Then I get a newly imported hashset of customer objects and have to check for every new object, if it is contained in the existing hashset.然后我得到一个新导入的客户对象哈希集,并且必须检查每个新的 object,如果它包含在现有的哈希集中。 Performance is very important.性能非常重要。

I cannot use the default Equalitycomparer as it needs to be compared based on only three properties.我不能使用默认的 Equalitycomparer,因为它只需要基于三个属性进行比较。 Also, I can't override the Equals and GetHashCode functions of the Customer class for other reasons.此外,由于其他原因,我无法覆盖客户 class 的 Equals 和 GetHashCode 函数。 So I aimed for a custom EqualityComparer (I tried implementing IEqualityComparer or inheriting from EqualityComparer and overriding like you see below - both with the same end result).因此,我的目标是自定义 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;
        }
    }

Now to my problem: When I use the default EqualityComparer, generally only the GetHashCode method of Customer is called and the performance for my use case is very good (1-2 seconds).现在我的问题是:当我使用默认的 EqualityComparer 时,通常只调用 Customer 的 GetHashCode 方法,并且我的用例的性能非常好(1-2 秒)。 When I use my custom EqualityComparer, the GetHashCode method is never called but always the Equals method.当我使用我的自定义 EqualityComparer 时,永远不会调用 GetHashCode 方法,但总是调用 Equals 方法。 The performance for my use case is horrible (hours).我的用例的性能很糟糕(几个小时)。 See code below:请参见下面的代码:

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))
        //...
        }            
    }
}

Does anyone have an idea, how I can solve this problem?有谁知道,我该如何解决这个问题? That would be amazing, I'm really stuck trying to solve this huge performance problem.那将是惊人的,我真的被困在试图解决这个巨大的性能问题。

EDIT:编辑:

I solved it by passing my EuqalityComparer when initializing the hashset!我在初始化哈希集时通过传递我的 EuqalityComparer 解决了这个问题! By using the constructor overload that takes an IEqualityComparer so var database = new HashSet(new CustomerComparer())通过使用采用 IEqualityComparer 的构造函数重载,因此 var database = new HashSet(new CustomerComparer())

Thank you, guys!感谢你们!

I solved it by passing my EqualityComparer when initializing the hashset!我通过在初始化哈希集时传递我的 EqualityComparer 来解决它! Is used the constructor overload that takes an IEqualityComparer so var database = new HashSet(new CustomerComparer())使用采用 IEqualityComparer 的构造函数重载,因此 var database = new HashSet(new CustomerComparer())

Thanks to Lee and NetMage who commented under my original post.感谢 Lee 和 NetMage 在我原来的帖子下发表评论。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM