2013-02-18 2 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(); 
} 

Я интересно знать, есть ли какая-либо причина, почему после нахождения более одного элемента в петле, там не является инструкцией break, чтобы исключить циклизацию остальной части списка. В любом случае произойдет ошибка. Для большого списка, где в начале найдено более одного элемента, я думаю, что это сделает огромную разницу.

+0

Где вы получите код? Декомпилированный? –

+0

Если вы посмотрите на перегрузку, не используя предикат, вы увидите, что она оптимизирована для IList и использует только два элемента. Я предполагаю, что ошибка не важна для оптимизации – adrianm

+0

@HamletHakobyan Да, я использовал Resharper. – Samuel

ответ

7

Джон Скит found this while reimplementing LINQ to objects as part of his EduLinq blog series:

Оказывается, что в LINQ к объектам, Перегрузка без предиката броска InvalidOperationException, как только они видят, второй элемент, но и перегруженные с предикатом держать итерацию даже тогда, когда они Мы видели второй элемент, соответствующий предикату. Это кажется мне смехотворно непоследовательным - я открыл проблему Connect об этом; посмотрим, что произойдет.

В Connect issue in question, Microsft говорят:

Это было бы здорово, чтобы очистить, так что итерация всю последовательность не требуется при использовании Single перегрузки, которая принимает предикат - мы могли бы не удается быстро найти второй матч, аналогичный тому, что мы делаем, когда не указано ни одного предиката.

Однако, как польза перфорации, которая будет иметься здесь будет ограниченно Single «s случае ошибки, этот вопрос в настоящее время падает чуть ниже нашу ошибку сортировки линии разреза. Мы отмечаем проблему «Не исправить», чтобы указать, что мы в настоящее время не отслеживаем, чтобы исправить эту проблему в следующей версии Visual Studio. Мы будем активировать эту ошибку в следующем году, если мы получим дальше, чем ожидалось через наш список сортировки ошибок, или если мы перечислим ошибку для следующей версии.

Это было в апреле 2011 года ...

+0

Большое спасибо. Посмотрев на реализацию Jon Skeet, я говорю своим коллегам, что это реализация, которую я искал пару часов назад. – Samuel

Смежные вопросы