返回 IEnumerable 并调用 ToArray 时的 LINQ 意外行为

本文关键字:LINQ 意外 时的 ToArray IEnumerable 调用 返回 | 更新日期: 2023-09-27 18:35:20

我注意到 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 的这种(对我来说)意外行为?

返回 IEnumerable 并调用 ToArray 时的 LINQ 意外行为

这是因为延迟执行。在执行 Linq 之前,不会对其进行计算。

ToArray()的调用会导致IEnumerable的完整枚举,从而发生异常。

第二种方法不枚举IEnumerable,并且执行将延迟到调用方需要它。


如果您要枚举Find的结果,例如

var result = Find(new[] { "name" }).ToList();

foreach (var found in Find(new[] { "name" }))
{
    ...
}

然后会发生异常。