考虑以下示例:
public IEnumerable<String> Test ()
{
IEnumerable<String> lexicalStrings = new List<String> { "test", "t" };
IEnumerable<String> allLexicals = new List<String> { "test", "Test", "T", "t" };
IEnumerable<String> lexicals = new List<String> ();
foreach (String s in lexicalStrings)
lexicals = lexicals.Union (allLexicals.Where (lexical => lexical == s));
return lexicals;
}
我希望它能产生“test”,“t”作为输出,但它没有(输出只是“t”)。我不确定,但可能需要对延迟处理做些什么。任何想法如何使这个工作或一个好的替代品?
编辑:请注意,这只是一个简化的示例。 lexicalStrings
和allLexicals
是原始代码中的不同类型。所以我不能直接结合这些。
Edit2要解决的问题看起来更像是这样:
public IEnumerable<Lexical> Test ()
{
IEnumerable<String> lexicalStrings = new List<String> { "test", "t" };
IEnumerable<Lexical> allLexicals = new List<Lexical> { ... };
IEnumerable<Lexical> lexicals = new List<Lexical> ();
foreach (String s in lexicalStrings)
lexicals = lexicals.Union (allLexicals.Where (lexical => lexical.Text == s));
return lexicals;
}
答案 0 :(得分:3)
您使用错误的操作作为其他答案解释。但仍然有趣的是,尽管看起来很好,但为什么你的代码工作不正确。
让我们稍微修改你的应用程序:
IEnumerable<String> lexicalStrings = new List<String> { "test", "t" };
IEnumerable<String> allLexicals = new List<String> { "test", "Test", "T", "t" };
IEnumerable<String> lexicals = new List<String>();
foreach (String s in lexicalStrings)
{
lexicals = lexicals.Union(
allLexicals.Where(
lexical =>
{
Console.WriteLine(s);
return lexical == s;
}
)
);
}
Console.WriteLine();
foreach (var item in lexicals)
{
}
您期望什么输出?这是它:
t
t
t
t
t
t
t
t
有趣的是,不是吗?
现在让我们再次修改它:
IEnumerable<String> lexicalStrings = new List<String> { "test", "t" };
IEnumerable<String> allLexicals = new List<String> { "test", "Test", "T", "t" };
IEnumerable<String> lexicals = new List<String>();
foreach (String s in lexicalStrings)
{
string ls = s;
lexicals = lexicals.Union(
allLexicals.Where(
lexical =>
{
Console.WriteLine(ls);
return lexical == ls;
}
)
);
}
foreach (var item in lexicals)
{
}
现在输出结果很好:
test
test
test
test
t
t
t
t
为什么会这样?你使用闭包 - 在内部lambda中使用外部var。由于您实际上没有迭代序列,因此s的当前值不会进入lambda。 foreach退出和s
的所有内部副本保存最后一次迭代的值。在内部变量的情况下,它们保存为每次迭代创建的值副本。这种冲突来自LINQ的内心懒惰。如果您执行List.AddRange
内部循环结果会很好,因为List.AddRange
会强制迭代。
答案 1 :(得分:1)
public IEnumerable<Lexical> Test ()
{
var lexicalStrings = new List<String> { "test", "t" };
var allLexicals = new List<Lexical> { ... };
var lexicals = new List<Lexical> ();
foreach (string s in lexicalStrings)
{
lexicals.AddRange(allLexicals.Where (lexical => lexical.Text == s));
}
return lexicals;
}
答案 2 :(得分:0)
这是你想要实现的目标吗?
lexicals.Union( allLexicals ).Distinct( StringComparer.OrdinalIgnoreCase )
编辑:
或者更好,因为@Dave建议:
lexicals.Intersect( allLexicals, StringComparer.OrdinalIgnoreCase )
编辑2:
如果它们是不同类型,则其中一个必须将 IEqualityComparer 实现到另一个。然后将此类传递给Intersect方法:
lexicals.Intersect( allLexicals, new MyCustomTComparer() )