Вы используете неправильную операцию в качестве объяснения другого ответа. Но все же интересно, почему ваш код работает некорректно, несмотря на то, что выглядит хорошо.
давайте немного изменим ваше приложение:
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
Почему это происходит? Вы используете закрытие - использование внешнего var во внутренней лямбде. Поскольку вы на самом деле не повторяете свою последовательность, текущее значение s не попадает в лямбду. выходы foreach и все внутренние копии s
содержат значение последней итерации. В случае внутренней переменной они содержат копии значений, которые создаются для каждой итерации. Этот конфликт происходит из-за внутренней лени LINQ. Если вы сделаете что-то вроде List.AddRange
внутри цикла, результат будет хорошим, потому что List.AddRange
вызывает итерацию.