简体   繁体   English

我应该如何实现IEqualityComparer <T> 。等于

[英]How should I implement IEqualityComparer<T>.Equals

Concerning IEqualityComparer, is there ever a reason why the Equals(T x, T y) implementation should be anything other than what I have below? 关于IEqualityComparer,是否有理由为什么Equals(T x, T y)实现应该是我下面所没有的?

public class MyEquality : IEqualityComparer<MyType>
{
    //My Equals(T x, T y) always looks like this
    public bool Equals(MyType x, MyType y)
    {
        return this.GetHashCode(x).Equals(this.GetHashCode(y));
    }

    public int GetHashCode(MyType obj)
    {
        //assume MyType has a non-nullable member called ID
        return obj.ID.GetHashCode();
    }
}

Yes. 是。 Hash codes can collide and in fact, they will with many types. 哈希码可能会冲突,实际上,它们会具有多种类型。 They only exist to ensure equidistribution of values in hash tables, they are not useful for determining equality of values. 它们仅存在以确保哈希表中的值相等分布,它们对确定值的相等性没有用。 Eric Lippert has also a take on this (and another one ): 埃里克利珀也有这样的取值(和另外一个 ):

It is a really bad idea to use 32 bit hash codes as “unique” identifiers. 使用32位哈希码作为“唯一”标识符是一个非常糟糕的主意。 Hash values aren't random per se, but if they're well-distributed then they might as well be for our purposes. 哈希值本身并不是随机的,但是如果它们分布合理,那么它们也很可能是我们的目的。 You might think “well, sure, obviously they are not truly unique since there are more than four billion possible values, but only four billion hash codes available. 您可能会想:“当然,显然它们并不是真正唯一的,因为可能的值超过40亿,但只有40亿的哈希码可用。 But there are so many possible hash values, odds are really good that I'm going to get unique values for my hashes”. 但是散列值太多了,赔率非常好,我将为我的散列获得唯一的值。” But are the chances really that good? 但是机会真的那么好吗? 9300 objects is not that many and 1% is a pretty high probability of collision. 9300个对象并不多,只有1%的对象发生碰撞的可能性很高。

That being said, if your ID is the only thing you care for when determining equality, then comparing that ID should suffice. 话虽如此,如果您的ID是确定相等性时唯一要注意的事情,那么比较该ID就足够了。 But not its hash code because a hash code only says 但不是其哈希码,因为哈希码仅表示

a .GetHashCode() ≠ b .GetHashCode() → ab a .GetHashCode()≠ b .GetHashCode()→ ab

Note that nothing is said about the case where the hash code is the same. 注意,对于哈希码相同的情况,没有任何说明。

Yes, there is: if ID 's hash code does not fit in an int , now or some time in the future, you would be in for a nasty surprise, when unequal objects with identical hash codes start evaluating as equals. 是的,有:如果ID的哈希码现在或将来某个时间不适合int ,当具有相同哈希码的不相等对象开始评估为相等时,您将感到非常讨厌。 If at a later date someone decides that ID should be long or Guid , MyEquality would continue to happily compile, but its behavior would be hopelessly incorrect. 如果以后有人决定ID应该是longGuid ,则MyEquality将继续愉快地进行编译,但是其行为将是无法避免的错误。

On an unrelated note, if MyType is a class, you may want to do something about preventing crashes when x or y is null : although the contract of IEqualityComparer<T> does not explicitly calls for it (unlike object.Equals that does) it is a good idea to deal with null s in IEqualityComparer<T>.Equals in situations when you search through containers that may include null objects. 无关紧要的是,如果MyType是一个类,则可能需要采取一些措施来防止xynull时崩溃:尽管IEqualityComparer<T>的协定没有明确要求它(与object.Equals一样)在IEqualityComparer<T>.Equals处理null是一个好主意。在您搜索可能包含null对象的容器时,该情况均IEqualityComparer<T>.Equals

Sure. 当然。 You could have an object where you're only concerned about one or more properties being the same to consider them equal for your purposes. 在一个对象中,您只关心一个或多个属性是相同的,就可以认为它们对于您的目的是相等的。

If you would compare List list1, and List list2, if they have some "common" element, for instance list1={"apparent", "obvious"}, and list2={"aPPARENT", "oBVIOUS"} 如果要比较列表list1和List list2,如果它们具有一些“公共”元素,例如list1 = {“ apparent”,“ obvious”}和list2 = {“ aPPARENT”,“ oBVIOUS”}

if your definition of equity is as follows: 如果您对权益的定义如下:

  • the first character must be equal, case sensitive 第一个字符必须相等,区分大小写
  • the remainder character must not be equal (case sensitive) 其余字符不能相等(区分大小写)

you must define your own logic in your IEqualityComparer. 您必须在IEqualityComparer中定义自己的逻辑。

Besides, in LINQ, all the Where, Any, Except, Intersect etc. clauses may require additional IEqualityComparer object for you to hook you custom logic. 此外,在LINQ中,所有Where,Any,Except,Intersect等子句都可能需要附加的IEqualityComparer对象,以挂钩自定义逻辑。

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

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