我应该如何实现IEqualityComparer <t> .Equals </t>

时间:2013-04-17 15:40:42

标签: c# equals gethashcode iequalitycomparer

关于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();
    }
}

4 个答案:

答案 0 :(得分:3)

是。哈希码可能会发生冲突,事实上,它们会有很多类型。它们仅用于确保哈希表中值的等分布,它们对于确定值的相等性没有用。 Eric Lippert也对此采取了措施(和another one):

  

使用32位哈希码作为“唯一”标识符是一个非常糟糕的主意。哈希值本身并不是随机的,但如果它们分布均匀,那么它们也可能用于我们的目的。您可能会认为“嗯,当然,它们并非真正独特,因为有超过40亿个可能的值,但只有40亿个哈希码可用。但是有很多可能的哈希值,很可能我将为哈希获得独特的价值“。但是机会真的那么好吗? 9300个物体并不多,1%的碰撞概率非常高。

话虽如此,如果您的ID是您在确定平等时唯一关心的事情,那么比较该ID就足够了。但不是它的哈希码,因为哈希码只是说

  

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

请注意,没有任何关于哈希码相同的情况。

答案 1 :(得分:2)

是的,有:如果ID的哈希码不适合int,现在或将来的某个时间,你会遇到一个令人讨厌的惊喜,当不平等的对象与相同的哈希码开始评估为等于。如果以后某人决定ID应该是longGuidMyEquality会继续愉快地编译,但其行为将无可救药地错误。

在不相关的说明中,如果MyType是一个类,您可能希望在xynull时防止崩溃:尽管合同是IEqualityComparer<T>没有明确地要求它(与object.Equals不同)在搜索可能的容器时,在null中处理IEqualityComparer<T>.Equals是个好主意包括null个对象。

答案 2 :(得分:0)

不确定。你可以有一个对象,你只关心一个或多个属性是相同的,认为它们是相同的。

答案 3 :(得分:0)

如果要比较List list1和List list2,如果它们有一些“common”元素,例如list1 = {“apparent”,“apparent”},list2 = {“aPPARENT”,“oBVIOUS”} < / p>

如果您对权益的定义如下:

  • 第一个字符必须相同,区分大小写
  • 剩余字符不能相等(区分大小写)

您必须在IEqualityComparer中定义自己的逻辑。

此外,在LINQ中,所有 Where,Any,Except,Intersect 等子句可能需要额外的IEqualityComparer对象,以便您自定义逻辑。