Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Optimization in the SingleOrDefault function of Linq

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.

like image 995
Samuel Avatar asked Feb 18 '13 16:02

Samuel


1 Answers

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...

like image 165
AakashM Avatar answered Nov 12 '22 02:11

AakashM