5

Here is the code extracted of the SingleOrDefault function:

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

I'm wondering to know if there is any reason why after finding more than one element in the loop, there is no break statement to prevent looping the rest of the list. In anyways, an error will occurs. For a big list where more than one item is found at the beginning, I think it would make a uge difference.

Samuel
  • 12,073
  • 5
  • 49
  • 71
  • Where are you get the code? Decompiled one? – Hamlet Hakobyan Feb 18 '13 at 16:09
  • If you look at the overload not taking a predicate you'll see that it is optimized for IList and only taking two elements. I assume the error case is not important to optimize – adrianm Feb 18 '13 at 16:13
  • @HamletHakobyan Yes, I used Resharper. – Samuel Feb 18 '13 at 16:15
  • 1
    possible duplicate of [Bad implementation of Enumerable.Single?](http://stackoverflow.com/questions/4825401/bad-implementation-of-enumerable-single) – Ani Feb 18 '13 at 16:16

1 Answers1

7

Jon Skeet found this while reimplementing LINQ to objects as part of his EduLinq blog series :

It turns out that in LINQ to Objects, the overloads without a predicate throw InvalidOperationException as soon as they see a second element, but the overloads with a predicate keep iterating even when they've seen a second element matching a predicate. This seems ludicrously inconsistent to me - I've opened a Connect issue about it; we'll see what happens.

In the Connect issue in question, Microsft say:

This would be great to clean up, so that iterating the entire sequence is not required when using the Single overload that takes a predicate - we could fail fast upon finding a second match, similar to what we do when no predicate is specified.

However, as the perf benefit to be had here would be limited to Single's error case, this issue currently falls just below our bug triage cut line. We're marking the issue Won't Fix to indicate that we're not currently tracking to fix this issue in the next release of Visual Studio. We'll reactivate this bug over the next year if we get further than expected through our bug triage list, or if we revisit the bug for the following release.

That was in April 2011...

AakashM
  • 62,551
  • 17
  • 151
  • 186