简体   繁体   English

如果我的类实现了IEqualityComparer,我应该实现非通用GetHashCode和Equals吗? <T> ?

[英]Should I implement non-generic GetHashCode and Equals if my class implements IEqualityComparer<T>?

Should I implement non-generic GetHashCode and Equals if my class implements IEqualityComparer<T> ? 如果我的类实现IEqualityComparer<T>是否应该实现非通用GetHashCodeEquals

Update: My hope was that MS updated implementation of their collection when they introduced IEqualityComparer<T> . 更新:我希望MS在引入IEqualityComparer<T>时更新其集合的实现。 So I thought that Dictionary and any other collection classes will check internally if my class implements IEqualityComparer<T> and use not generic methods GetHashCode and Equals only if that interface is not implemented. 因此,我认为Dictionary和其他任何收集类都将在内部检查我的类是否实现IEqualityComparer<T> ,并且仅在未实现该接口的情况下才使用非通用方法GetHashCodeEquals Without collections support that interface has very little value. 没有集合支持,该接口几乎没有价值。

Update2: I just checked Dictionary.FindEntry(TKey key) using ILSpy. Update2:我刚刚使用ILSpy检查了Dictionary.FindEntry(TKey key) It uses IEqualityComparer<TKey> (varriable comparer below). 它使用IEqualityComparer<TKey> (下面的可变comparer )。 In fact I did not find any using of not generic GetHashCode and Equals functions at all. 实际上,我根本没有发现任何非通用GetHashCodeEquals函数的使用。

int num = this.comparer.GetHashCode(key) & 2147483647;
for (int i = this.buckets[num % this.buckets.Length]; i >= 0; i = this.entries[i].next)
{
    if (this.entries[i].hashCode == num
                && this.comparer.Equals(this.entries[i].key, key))
    {
        return i;
    }
}

So it seems to that my class only needs to implement IEqualityComparer<T> to be properly used with Dictionary . 因此,看来我的课程只需要实现IEqualityComparer<T>即可与Dictionary一起正确使用。

I understand that there will be no harm to implement not generic functions just in case. 我知道,以防万一,实现非通用功能不会有任何危害。

But should we spend time if it brings no value? 但是,如果没有任何价值,我们应该花费时间吗?

I will make my question more specific: 我将提出更具体的问题:

Should I implement non-generic GetHashCode and Equals if my class implements IEqualityComparer<T> and: 如果我的类实现了IEqualityComparer<T>并且应该实现非通用GetHashCodeEquals则:

  1. I do not use not generic collections in my code 我在代码中不使用非通用集合
  2. Third party code does not call GetHashCode and Equals methods of my code. 第三方代码不会调用我的代码的GetHashCodeEquals方法。

Does Microsoft code still needs non generic versions to work properly? Microsoft代码是否仍需要非通用版本才能正常工作?

Update3 : I think I got it. Update3 :我想我明白了。 I thought that IEqualityComparer<T> is to be implemented inside my class. 我认为IEqualityComparer<T>将在我的课程中实现。 In that case we would have generic and not generic versions of methods in one place. 在那种情况下,我们将在一个地方拥有方法的通用版本而非通用版本。 That is not how IEqualityComparer<T> should be used. 那不是应该使用IEqualityComparer<T>方式。 It should be implemented as separate class and used as parameter. 应该将其实现为单独的类并用作参数。

Thanks to everybody. 感谢大家。

It depends. 这取决于。 IEqualityComparer<T> is used to compare two instances of a type T - and typically implemented by a separate comparer class. IEqualityComparer<T>用于比较类型T两个实例-通常由单独的比较器类实现。 Normally you wouldn't not implement this in the class type T . 通常,您不会在类类型T实现它。 It's meant to provide an alternative comparison for use with types that support his. 它旨在提供另一种比较,以与支持他的类型一起使用。

If you're implementing this within the class itself, you'd typically implement IEquatable<T> . 如果要在类本身中实现此功能,则通常要实现IEquatable<T>

That being said, it's often useful to override Object.Equals , which is typically very simple as you can use the IEquatable<T>.Equals method to implement Object.Equals . 话虽如此,重写Object.Equals通常很有用,因为您可以使用IEquatable<T>.Equals方法来实现Object.Equals ,这通常非常简单。 This makes it "inexpensive" to implement. 这使得实施“便宜”。 As Object.Equals may be used, it will provide a consistent meaning to equality, so it's generally a good idea to implement. 由于可能使用Object.Equals ,它将为相等性提供一致的含义,因此通常实现是一个好主意。

If your object is going to be used as a key in a hash, such as a Dictionary<T,U> or a HashSet<T> , then you should override GetHashCode . 如果您的对象将用作哈希(例如Dictionary<T,U>HashSet<T> ,则应重写GetHashCode If there's even a chance that it may be used in this manner, overriding this method is beneficial. 如果甚至有可能以这种方式使用它,则重写此方法将是有益的。 Typically, I find that it's useful to override GetHashCode any time I implement equality, just in case I will use the type as a key later. 通常,我发现在实现相等性的任何时候重写GetHashCode都是有用的,以防万一我以后将类型用作键。

IEqualityComparer is meant to replace the default implemenation of GetHashCode and Equals every .NET object already has. IEqualityComparer旨在替换GetHashCode的默认实现,并等于每个.NET对象已经拥有。 This interface is only used by Dictionaries and (Hash)Sets to use a different hashing and comparison scheme as the object by default uses. 默认情况下,此字典接口仅由Dictionary和(Hash)Set用来将不同的哈希和比较方案用作对象。

If your object is used in Dictionaries and HashTables as key you should first to override Equals and GetHashCode to let the Sets/Dictionaries use the default comparer (the one you call EqualityComparere.Default) for your object which does call Equals and GetHashCode of your object anyway. 如果您的对象在“字典”和“哈希表”中用作键,则应首先覆盖Equals和GetHashCode,以使Sets / Dictionaries为您的对象使用默认的比较器(您将其称为EqualityComparere.Default),该比较器会调用对象的Equals和GetHashCode无论如何。

The only reason to provide an external comparer via IEqualityComparer is to use a different comparison scheme. 通过IEqualityComparer提供外部比较器的唯一原因是使用不同的比较方案。 Eg for strings you can choose from the BCL StringComparer class between case sensitive and case insensitive variants. 例如,对于字符串,您可以从BCL StringComparer类中选择区分大小写和不区分大小写的变体。

Update1 UPDATE1

The intention of this question was why List and other collections always use the default comparer and not the one provided by the object. 这个问题的目的是为什么List和其他集合始终使用默认比较器,而不使用对象提供的比较器。 If an object does implement Equals and GetHashCode already why should List not use them if the object does at the same time also implements IEqualityComparer? 如果一个对象确实已经实现了Equals和GetHashCode,如果该对象同时也实现了IEqualityComparer,为什么List不应该使用它们? Since List does not provide a ctor which does allow to use a different comparer it does need to use the default one. 由于List没有提供允许使用其他比较器的ctor,因此确实需要使用默认比较器。

But if you want to use different ones you always can use LINQ which does fix this issue by allowing you to pass explicitely your own comparer for a specific metho. 但是,如果您想使用不同的比较器,则始终可以使用LINQ,它可以通过允许您明确地传递自己的特定方法的比较器来解决此问题。 Eg Enumerable.Contains has an overload where you can pass in your own comparer. 例如Enumerable.Contains有一个重载,您可以在其中传递自己的比较器。

From MSDN Sample: 从MSDN示例:

Product[] fruits = { new Product { Name = "apple", Code = 9 }, 
                       new Product { Name = "orange", Code = 4 }, 
                       new Product { Name = "lemon", Code = 12 } };

Product apple = new Product { Name = "apple", Code = 9 };
Product kiwi = new Product {Name = "kiwi", Code = 8 };

ProductComparer prodc = new ProductComparer();

bool hasApple = fruits.Contains(apple, prodc);
bool hasKiwi = fruits.Contains(kiwi, prodc);

If I understand you correctly and you're asking if you also have to implement IEqualityComparer if you implement IEqualityComparer<T> , then the answer is you don't have to, but it's probably a good idea. 如果我正确理解您的要求,并且您问是否还必须实现IEqualityComparer如果您实现IEqualityComparer<T> ,那么答案是不必这样做,但这可能是个好主意。 It will just make your comparer more compatible with existing code. 这只会使您的比较器与现有代码更加兼容。

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

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