5

下面是从 SingleOrDefault 函数中提取的代码:

public static TSource SingleOrDefault<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate) { 
    if (source == null) throw Error.ArgumentNull("source");
    if (predicate == null) throw Error.ArgumentNull("predicate");
    TSource result = default(TSource);
    long count = 0; 
    foreach (TSource element in source) {
        if (predicate(element)) { 
            result = element; 
            checked { count++; }
        } 
    }
    switch (count) {
        case 0: return default(TSource);
        case 1: return result; 
    }
    throw Error.MoreThanOneMatch(); 
} 

我想知道是否有任何理由在循环中找到多个元素后,没有 break 语句来防止循环列表的其余部分。无论如何,都会发生错误。对于一开始就发现不止一个项目的大列表,我认为这会产生巨大的影响。

4

1 回答 1

7

Jon Skeet在他的 EduLinq 博客系列中重新实现 LINQ to objects 时发现了这一点

事实证明,在 LINQ to Objects 中,没有谓词的重载在看到第二个元素时会立即抛出 InvalidOperationException,但带有谓词的重载即使在看到与谓词匹配的第二个元素时也会继续迭代。这对我来说似乎是荒谬的不一致——我已经打开了一个关于它的 Connect 问题;我们会看看会发生什么。

在有问题的Connect 问题中,Microsft 说:

这将是很好的清理,因此在使用带有谓词的重载时不需要迭代整个序列Single- 我们可能会在找到第二个匹配时快速失败,类似于我们在没有指定谓词时所做的事情。

但是,由于此处的性能优势将仅限于 Single' 错误情况,因此此问题目前刚好低于我们的错误分类切割线。我们将问题标记为“无法修复”以表明我们目前未跟踪在 Visual Studio 的下一版本中修复此问题。如果我们通过错误分类列表获得的结果超出预期,或者如果我们在下一个版本中重新访问该错误,我们将在明年重新激活此错误。

那是2011年4月...

于 2013-02-18T16:12:50.563 回答