我注意到LINQ代码中有一些奇怪的行为,并使用两种方法将问题减少到以下最小示例:
IA Find(string n)
{
IA result;
if (!_dictionary.TryGetValue(n, out result))
{
throw Exception();
}
return result;
}
IEnumerable<IA> Find(IEnumerable<string> names)
{
return names.Select(Find).ToArray();
}
这可以按预期工作。
现在,我删除了.ToArray(),因此该方法如下所示:
IEnumerable<IA> Find(IEnumerable<string> names)
{
return names.Select(Find);
}
此更改将导致不抛出异常,即使在_dictionary中找不到某些名称,但在names参数中也存在这些名称。
导致这种(对我而言)LINQ意外行为的原因是什么?
答案 0 :(得分:14)
因为延期执行。在执行Linq之前,不会对其进行评估。
对ToArray()
的调用会导致IEnumerable
的完全枚举,从而发生异常。
第二种方法不会枚举IEnumerable
,并且会延迟执行,直到调用者需要它为止。
如果您要枚举Find
例如
var result = Find(new[] { "name" }).ToList();
或
foreach (var found in Find(new[] { "name" }))
{
...
}
然后会发生异常。