2

我在几个地方读到 LINQ 等于(在连接语法中)调用 IEquatable 来比较它的类型,但我没有看到它在我的连接中发生:

List<ILData> list1 = new List<ILData> { /* Initialized with items */ };
List<ILData> list2 = new List<ILData> { /* Initialized with items */ };

var joinItems = (
    from d1 in list1
        join d2 in list2
        on d1 equals d2
    where d1.SomeValue == "7"
    select d1).Distinct().ToList<ILData>();

假设我提供了一个满足的接口定义:

ILData : IEquatable<ILData>

要求,为什么在这种情况下我不会看到 ILData::Equals 被调用?

4

2 回答 2

5

它使用EqualityComparer<T>.Default. 由于您的类型 implements IEquatable<T>,实际使用的比较器将是一个名为 的内部类 System.Collections.Generic.GenericEqualityComparer<T>,它将分别委托GetHashCodeEquals请求您的object.GetHashCode方法和IEquatable<ILData>.Equals方法(引用除外null,它返回零哈希码/不调用您方法)。

有很多原因可以解释你的Equals方法没有被击中:

  1. 这里有一个空序列。
  2. 你的断点在object.Equals而不是IEquatable<ILData>.Equals
  3. 第二个序列只包含null引用(这是由框架比较器检查的,所以它不会进入你的)。
  4. 没有哈希匹配(来自GetHashCode),因此连接操作永远不需要进行完全相等检查。可能发生这种情况的一个原因是您忘记覆盖此方法,因此坚持使用默认的 from object(它是为引用相等而设计的,并且与您对相等的定义不一致)。
于 2012-07-10T16:07:21.970 回答
0

Join 函数说它使用默认的相等比较器。除了实现 IEquatable 之外,您还需要覆盖 object.GetHashCode(并且应该覆盖 object.Equals)。

一般来说,查询

from AA in AAAA
join BB in BBBB
on C(AA) equals D(BB)
select E(AA,BB)

翻译成

AAAA.Join(BBBB, AA => C(AA), BB => D(BB), (AA, BB) => E(AA, BB))
于 2012-07-10T16:11:12.620 回答