1

我在 VS 2010 中使用 C# 4.0 并尝试生成 n 组对象的交集或并集。

以下工作正常:

IEnumerable<String> t1 = new List<string>() { "one", "two", "three" };
IEnumerable<String> t2 = new List<string>() { "three", "four", "five" };

List<String> tInt = t1.Intersect(t2).ToList<String>();
List<String> tUnion = t1.Union(t2).ToList<String>();
//  this also works
t1 = t1.Union(t2);
//  as does this (but not at the same time!)
t1 = t1.Intersect(t2);

但是,以下没有。这些是代码片段。

我的课是:

 public class ICD10
{
    public string ICD10Code { get; set; }
    public string ICD10CodeSearchTitle { get; set; }
}

在下面的:

IEnumerable<ICD10Codes> codes = Enumerable.Empty<ICD10Codes>();
IEnumerable<ICD10Codes> codesTemp;
List<List<String>> terms;
//  I create terms here ----
// and then ...
foreach (List<string> item in terms)
{
    //  the following line produces the correct results
    codesTemp = dataContextCommonCodes.ICD10Codes.Where(e => item.Any(k => e.ICD10CodeSearchTitle.Contains(k)));

    if (codes.Count() == 0)
    {
        codes = codesTemp;
    }
    else if (intersectionRequired)
    {
        codes = codes.Intersect(codesTemp, new ICD10Comparer());
    }
    else
    {
        codes = codes.Union(codesTemp, new ICD10Comparer());
    }                
}
return codes;

以上只返回最后一个搜索项目的结果。

为了以防万一,我还添加了自己的比较器,但这没有什么区别:

public class ICD10Comparer : IEqualityComparer<ICD10Codes>
{
    public bool Equals(ICD10Codes Code1, ICD10Codes Code2)
    {
        if (Code1.ICD10Code == Code2.ICD10Code) { return true; }
        return false;
    }
    public int GetHashCode(ICD10Codes Code1)
    {
        return Code1.ICD10Code.GetHashCode();
    }
}

我确信我忽略了一些明显的东西——我只是看不到它是什么!

4

3 回答 3

3

This code: return codes; returns a deferred enumerable. None of the queries have been executed to fill the set. Some queries get executed each time through the loop to make a Count though.

This deferred execution is a problem because of the closure issue... at the return, item is bound to the last loop execution.

Resolve this by forcing the queries to execute in each loop execution:

if (codes.Count() == 0)
{
    codes = codesTemp.ToList();
}
else if (intersectionRequired)
{
    codes = codes.Intersect(codesTemp, new ICD10Comparer()).ToList();
}
else
{
    codes = codes.Union(codesTemp, new ICD10Comparer()).ToList();
}   
于 2013-04-07T21:54:23.193 回答
1

如果您使用自己的比较器,则应该查看该GetHashCode函数的正确实现。linq 运算符也使用此比较。你可以看看这里: http: //msdn.microsoft.com/en-us/library/system.object.gethashcode (v=vs.80).aspx

you could try changing the hash function to "return 0", to see if it is the problem. ICD10Code.GetHashCode will return perhaps different values if it is a class object

于 2013-04-07T21:43:06.200 回答
0

Your problem definitely is not connect to Intersect or Union LINQ extension methods. I've just tested following:

var t1 = new List<ICD10>()
    {
        new ICD10() { ICD10Code = "123" },
        new ICD10() { ICD10Code = "234" },
        new ICD10() { ICD10Code = "345" }
    };
var t2 = new List<ICD10>()
    {
        new ICD10() { ICD10Code = "234" },
        new ICD10() { ICD10Code = "456" }
    };

// returns list with just one element - the one with ICF10Code == "234"
var results = t1.Intersect(t2, new ICD10Comparer()).ToList();

// return list with 4 elements
var results2 = t1.Union(t2, new ICD10Comparer()).ToList();

Using your ICD10 and ICD10Comparer classes declarations. Everything works just fine! You have to search for bug in your custom code, because LINQ works just fine.

于 2013-04-07T21:50:57.560 回答