2013-02-18 7 views
5

Oto kod ekstrakcji funkcji SingleOrDefault:Optymalizacja funkcji 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(); 
} 

Zastanawiam się dowiedzieć, czy istnieje jakikolwiek powód, dlaczego po znalezieniu więcej niż jeden element w pętli, nie nie ma instrukcji break, aby zapobiec zapętleniu reszty listy. W każdym razie wystąpi błąd. W przypadku dużej listy, na której na początku znaleziono więcej niż jeden przedmiot, myślę, że spowodowałoby to różnicę.

+0

Gdzie masz kodu? Dekompilowany? –

+0

Jeśli spojrzysz na przeciążenie, które nie przyjmuje predykatu, zobaczysz, że jest zoptymalizowany pod kątem IList i bierze tylko dwa elementy. Zakładam, że przypadek błędu nie jest ważny dla optymalizacji – adrianm

+0

@HamletHakobyan Tak, użyłem Resharpera. – Samuel

Odpowiedz

7

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

Okazuje się, że w LINQ to Objects, że przeciążenia bez kwantyfikatorów rzutów InvalidOperationException tak szybko, jak widzą drugi element, ale przeciążenia z orzecznika Wciąż iteracja nawet gdy Widziałem drugi element pasujący do predykatu. Wydaje mi się to absurdalne - otworzyłem kwestię związaną z Connectem; zobaczymy co się stanie.

W Connect issue in question, Microsft powiedzieć:

Byłby to wielki, aby oczyścić tak, że iteracja całą sekwencję nie jest wymagane w przypadku korzystania z przeciążenia Single że trwa orzecznik - możemy nie działa szybko po znalezieniu drugiego dopasowania, podobnie do tego, co robimy, gdy nie jest określony żaden predykat.

Jednakże, jak korzyści, które można uzyskać perf tutaj byłaby ograniczona do Single „s błędu przypadku kwestia ta spoczywa obecnie tuż pod naszym bug triage linii cięcia. Problem nie zostanie naprawiony, aby wskazać, że nie śledzimy obecnie, aby rozwiązać ten problem w następnej wersji programu Visual Studio. Ponownie aktywujemy ten błąd w ciągu następnego roku, jeśli otrzymamy dalej niż oczekiwaliśmy na naszej liście błędów błędów, lub jeśli ponownie zgłoszę błąd w następnej wersji.

To było w kwietniu 2011 roku ...

+0

Dziękuję bardzo. Po przejrzeniu implementacji Jona Skeeta mówię moim współpracownikom, że jest to implementacja, której szukałem kilka godzin temu. – Samuel