繁体   English   中英

IEqualityComparer重载的GroupJoin仅比较内部集合中的对象

[英]GroupJoin overloaded with IEqualityComparer only compares objects in the inner collection

在与客户IEqualityComparer实施组加入时,我遇到了一些奇怪的行为。

以下代码演示了对我来说是问题的行为

List<String> inner = new List<string>() { "i1", "i2" };
List<String> outer = new List<string>() { "o1", "o2" };

var grouped = outer.GroupJoin(inner, i => i, o=> o, (inKey, outCollection) => new {Key = inKey, List = outCollection},
        new EqualityComparer<string>((i, o) => i == o)).ToList();

MSDN上找到的文档中,我希望最后一个参数将传递一系列内部键和外部键进行比较。

但是,在Func内放置一个断点表明,i和o都以字母i开头,并且实际上都是内部集合的两个元素,因此, grouped对象始终为空(我知道示例将始终为空,只是最小的一个)展示问题的代码)。

有没有办法使用自定义比较器对GroupJoin对象进行处理?

为了完整起见,这是在GroupJoin参数列表中创建的EqualityComparer:

public class EqualityComparer<T> : IEqualityComparer<T>
{
    public EqualityComparer(Func<T, T, bool> cmp)
    {
        this.cmp = cmp;
    }
    public bool Equals(T x, T y)
    {
        return cmp(x, y);
    }

    public int GetHashCode(T obj)
    {
        // Always return 0 so that the function is called
        return 0;
    }

    public Func<T, T, bool> cmp { get; set; }
}

GroupJoin操作首先需要建立查找-基本上是从inner每个投影键到具有该键的inner元素的查找。 这就是为什么要传递inner值的原因。 就“请求第一个结果时”而言,这种情况比较懒惰,但此时将消耗整个inner

然后,一旦建立了查找,就将outer元素流式传输,一次仅一个元素。 此时,应该要求您的自定义相等比较器将内部键与外部键进行比较。 实际上,当我向比较器添加日志记录时(为了避免与框架EqualityComparer<T>类型发生冲突,我已对其进行了重命名),我看到了:

using System;
using System.Linq;
using System.Collections.Generic;

public class Test
{
    public static void Main()
    {
        List<String> inner = new List<string>() { "i1", "i2" };
        List<String> outer = new List<string>() { "o1", "o2" };

        outer.GroupJoin(inner, i => i, o=> o,
            (inKey, outCollection) => new {Key = inKey, List = outCollection},
            new CustomEqualityComparer<string>((i, o) => i == o)).ToList();
    }
}

public class CustomEqualityComparer<T> : IEqualityComparer<T>
{
    public CustomEqualityComparer(Func<T, T, bool> cmp)
    {
        this.cmp = cmp;
    }
    public bool Equals(T x, T y)
    {
        Console.WriteLine("Comparing {0} and {1}", x, y);
        return cmp(x, y);
    }

    public int GetHashCode(T obj)
    {
        // Always return 0 so that the function is called
        return 0;
    }

    public Func<T, T, bool> cmp { get; set; }
}

输出:

Comparing i1 and i2
Comparing i1 and i2
Comparing i1 and i2
Comparing i2 and o1
Comparing i1 and o1
Comparing i2 and o2
Comparing i1 and o2

现在,这不是GroupJoin 唯一可能的实现,但这是一个相当明显的实现。 见我Edulinq后GroupJoin更多的细节。

暂无
暂无

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

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