C# 我应该如何实现IEqualityComparer.Equals

C# 我应该如何实现IEqualityComparer.Equals,c#,equals,gethashcode,iequalitycomparer,C#,Equals,Gethashcode,Iequalitycomparer,关于IEqualityComparer,除了我下面介绍的内容之外,还有什么理由让EqualsT 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).

关于IEqualityComparer,除了我下面介绍的内容之外,还有什么理由让EqualsT 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();
    }
}

对。散列代码可能会发生冲突,事实上,它们会与许多类型发生冲突。它们的存在只是为了确保散列表中值的均匀分布,对于确定值的相等性没有用处。也有这样的想法,并且:

使用32位哈希代码作为“唯一”标识符是一个非常糟糕的主意。散列值本身并不是随机的,但如果它们分布均匀,那么它们也可能用于我们的目的。你可能会想,“好吧,当然,很明显,它们不是唯一的,因为有四十多亿个可能的值,但只有四十亿个哈希代码可用。但是有这么多可能的哈希值,我很可能会得到唯一的哈希值。”。但机会真的那么好吗?9300个物体并不多,1%的碰撞概率相当高

也就是说,如果你的ID是你在决定平等性时唯一关心的东西,那么比较这个ID就足够了。但不是它的散列码,因为散列码只表示

a、 GetHashCode≠ b、 GetHashCode→ A.≠ b


请注意,对于哈希代码相同的情况,没有任何说明。

是。散列代码可能会发生冲突,事实上,它们会与许多类型发生冲突。它们的存在只是为了确保散列表中值的均匀分布,对于确定值的相等性没有用处。也有这样的想法,并且:

使用32位哈希代码作为“唯一”标识符是一个非常糟糕的主意。散列值本身并不是随机的,但如果它们分布均匀,那么它们也可能用于我们的目的。你可能会想,“好吧,当然,很明显,它们不是唯一的,因为有四十多亿个可能的值,但只有四十亿个哈希代码可用。但是有这么多可能的哈希值,我很可能会得到唯一的哈希值。”。但机会真的那么好吗?9300个物体并不多,1%的碰撞概率相当高

也就是说,如果你的ID是你在决定平等性时唯一关心的东西,那么比较这个ID就足够了。但不是它的散列码,因为散列码只表示

a、 GetHashCode≠ b、 GetHashCode→ A.≠ b

请注意,对于散列码相同的情况,没有任何说明。

是的,有:如果ID的散列码不适合整数,那么现在或将来某个时候,当具有相同散列码的不相等对象开始以相等的方式计算时,您会感到非常意外。如果以后有人决定ID应该是long或Guid,MyEquality将继续愉快地编译,但它的行为将是完全错误的

另一方面,如果MyType是一个类,当x或y为null时,您可能需要做一些防止崩溃的事情:尽管IEqualityComparer的契约没有明确地调用它,而不像object。Equals那样做。在IEqualityComparer中处理null是一个好主意。当您搜索可能包含null对象的容器时,Equals是,问题是:如果ID的散列码不适合整数,现在或将来某个时候,当具有相同散列码的不相等对象开始以相等值计算时,您可能会感到非常意外。如果以后有人决定ID应该是long或Guid,MyEquality将继续愉快地编译,但它的行为将是完全错误的


另一方面,如果MyType是一个类,当x或y为null时,您可能需要做一些防止崩溃的事情:尽管IEqualityComparer的契约没有明确地调用它,而不像object。Equals那样做。在IEqualityComparer中处理null是一个好主意。当您搜索可能包含null对象的容器时,Equals是一个好主意。

当然。你可以有一个对象,你只关心一个或多个属性是相同的,以考虑它们与你的目的相等。

< P>当然。你可以有一个对象,你只关心一个或多个属性,以考虑它们对于你的目的是相等的。

如果你比较列表List1和列表List2,如果它们有一些共同的元素,例如List1= {表观,明显},和List2= {表观,明显}

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

第一个字符必须相等,区分大小写 余数字符不能相等,区分大小写 您必须在iQualityComparer中定义自己的逻辑


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

如果您要比较列表list1和列表list2,如果它们有一些公共元素,例如list1={EXCENATIONE,EXCENATIONE}和list2={EXCENATIONE,EXCENATIONE}

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

第一个字符必须相等,区分大小写 余数字符不能相等,区分大小写 您必须在iQualityComparer中定义自己的逻辑


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

换句话说,如果a.GetHashCode!=b、 GetHashCode返回false是该方法的一半。另一半是比较对象a和b的实际值,因为它们具有相同的哈希代码。也就是说,如果计算哈希代码实际上比比较值要少的话。由于它们通常访问相同的字段,我想如果哈希代码不匹配,只需提前跳出就可以访问所有字段两次,而不是因为第一次比较已返回false而提前跳出。换句话说,如果a.GetHashCode!=b、 GetHashCode返回false是该方法的一半。另一半是比较对象a和b的实际值,因为它们具有相同的哈希代码。也就是说,如果计算哈希代码实际上比比较值要少的话。由于它们通常访问相同的字段,我想如果哈希代码不匹配,那么只需提前跳出就可以访问所有字段两次,而不是提前跳出,因为第一次比较已经返回false。