gpt4 book ai didi

c# - LINQ Distinct with EqualityComparer.Default : IEquatable implementation ignored?

转载 作者:太空宇宙 更新时间:2023-11-03 21:46:27 24 4
gpt4 key购买 nike

我有一个类Foo有两个字段,其中 EqualsGetHashCode方法已被覆盖:

public class Foo
{
private readonly int _x;
private readonly int _y;

public Foo(int x, int y) { _x = x; _y = y; }

public override bool Equals(object obj) {
Foo other = obj as Foo;
return other != null && _y == other._y;
}

public override int GetHashCode() { return _y; }
}

如果我创建一个 Foo 的数组:s 并计算 Distinct 的数量这个数组的值:

var array = new[] { new Foo(1, 1), new Foo(1, 2), new Foo(2, 2), new Foo(3, 2) };
Console.WriteLine(array.Distinct().Count());

不同值的数量被识别为:

2

如果我现在上课 Foo实现 IEquatable<Foo>使用以下实现:

public bool Equals(Foo other) { return _y == other._y; }

不同值的数量仍然是:

2

但是如果我将实现更改为:

public bool Equals(Foo other) { return _x == other._x; }

计算出的不同数量 Foo :s 既不是 3(即不同的 _x 的数量)也不是 2(不同的 _y 的数量),而是:

4

如果我注释掉 EqualsGetHashCode覆盖但保留 IEquatable<Foo>执行,答案也是4 .

根据 MSDN documentation , 这个Distinct重载应该使用静态属性 EqualityComparer.Default定义相等比较,并且:

The Default property checks whether type T implements the System.IEquatable<T>
interface and, if so, returns an EqualityComparer<T> that uses that
implementation. Otherwise, it returns an EqualityComparer<T> that uses the
overrides of Object.Equals and Object.GetHashCode provided by T.

但是从上面的实验来看,这个说法似乎并不成立。充其量,IEquatable<Foo>实现支持已经提供的 EqualsGetHashCode覆盖,在最坏的情况下,它会完全破坏相等性比较。

我的问题:

  • 为什么独立执行IEquatable<T>破坏平等比较?
  • 它能独立于Equals发挥作用吗?和 GetHashCode覆盖?
  • 如果不是,为什么 EqualityComparer<T>.Default先寻找这个实现?

最佳答案

你的 GetHashCode方法取决于y .这意味着如果你的 Equals方法取决于y ,你违反了平等契约……它们是不一致的。

Distinct()将期望相等的元素具有相同的哈希码。在您的情况下,唯一相等的元素 x值具有不同 哈希码,因此 Equals甚至不会被调用。

来自 IEquatable<T>.Equals 的文档:

If you implement Equals, you should also override the base class implementations of Object.Equals(Object) and GetHashCode so that their behavior is consistent with that of the IEquatable<T>.Equals method.

您对 Equals(Foo) 的实现不符合任一个 Equals(object) GetHashCode .

EqualityComparer<T>.Default仍然会委托(delegate)给你的 GetHashCode方法 - 它只会使用你的 Equals(T)方法优于您的 Equals(object)方法。

所以按顺序回答你的问题:

  • Why does the independent implementation of IEquatable<T> corrupt the equality comparison?

因为您引入了不一致的实现。它并不意味着在行为方面是独立的。它只是为了通过避免类型检查(和值类型的装箱)来提高效率。

  • Can it play a role independent of the Equals and GetHashCode overrides?

应该和Equals(object)一致为了理智,它必须GetHashCode一致为了正确起见。

If not, why does EqualityComparer<T>.Default look for this implementation first?

主要是为了避免运行时类型检查和装箱/拆箱。

关于c# - LINQ Distinct with EqualityComparer<T>.Default : IEquatable<T> implementation ignored?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16762989/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com