2013-02-18 48 views
5

这里的的SingleOrDefault功能是功能的SingleOrDefault提取代码:优化Linq中

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(); 
} 

我想知道是否有任何理由在循环寻找一个以上的元素后,有没有中断语句来防止循环列表的其余部分。无论如何,会发生错误。对于一开始就有一个以上的产品被发现的大列表,我认为它会产生巨大的差异。

+0

你在哪里得到的代码?反编译? – 2013-02-18 16:09:00

+0

如果你看一下没有使用谓词的重载,你会发现它是针对IList进行优化的,只有两个元素。我认为错误的情况下优化并不重要 – adrianm 2013-02-18 16:13:18

+0

@HamletHakobyan是的,我用Resharper。 – Samuel 2013-02-18 16:15:23

回答

7

乔恩斯基特found this while reimplementing LINQ to objects as part of his EduLinq blog series

事实证明,在LINQ到对象,没有一个谓语扔出现InvalidOperationException重载只要他们看到第二个元素,但重载与谓语保持均匀的迭代它们时已经看到了与谓词匹配的第二个元素。这对我来说似乎是非常不一致的 - 我已经为此打开了连接问题;我们会看到会发生什么。

Connect issue in question,的Microsft说:

这将是伟大的清理,使迭代整个序列使用Single重载需要一个谓语 时 不需要 - 我们可以在找到第二个匹配时失败很快,类似于我们在没有指定谓词时所做的操作。

然而,由于在这里有PERF利益将仅限于 Single的错误的情况下,这个问题目前正好落在我们的错误 分流切割线以下。我们将问题标记为“无法修复”,表示我们目前没有跟踪在下一个版本的 Visual Studio中修复此问题。如果我们通过bug分类列表获得 以上的预期,或者我们重新访问 以下版本的bug,我们将在下一年重新激活此bug。

那是在2011年4月...

+0

非常感谢。在看了Jon Skeet的实现之后,我对同事说,这是我几个小时前正在寻找的实现。 – Samuel 2013-02-18 16:22:56