Linq делает много умных вещей, таких как возврат результата свойства количества с помощью Count
() метод на a IList
. Существует ли хороший источник, который дает обзор этого оптимизация?
Это было бы очень интересно, потому что как, прежде чем я знал вышеупомянутое, я никогда не использовал Count()
и таким образом часто возвращал a List<T>
чем только IEnumerable<T>
потому что я знал, что вызывающая сторона должна будет нуждаться часто в количестве экземпляра списка.
Но имение в виду того количества () действительно не считает экземпляры содержавшимися в IEnumerable<T>
но возвращает результат свойства количества из возвращенного Списка, и поэтому не выпуск производительности причинил меня для изменения большого количества моих типов возврата от Списка до IEnumerable<T>
.
Текущие оптимизации, о которых я знаю:
Count
использует Count
, если последовательность реализует ICollection
и предикат не используется. (В .NET 4 Count
также оптимизирован для неуниверсального ICollection
.)
ElementAt
/ ElementAtOrDefault
доступ по индексу, если последовательность реализует IList
.
Последний доступ
/ LastOrDefault
по индексу, если последовательность реализует IList
и предикат не используется.
ToArray
/ ToList
используют свойство Count
для более эффективного распределения памяти, если последовательность реализует ICollection
. (Но ни один из них не оптимизируется для ICollection
.)
Оптимизации, которые могут быть, но отсутствуют:
Last
/ LastOrDefault
не оптимизируются в случае использования предиката. Нет причин, по которым они не могли оптимизировать для IList
, выполняя итерацию назад по списку и получая доступ к каждому элементу по индексу.
SequenceEqual
может оптимизировать для ICollection
и ICollection
, используя свойство Count
, чтобы определить, имеют ли списки одинаковую длину и разрывы. рано, если они не.
Skip
может оптимизировать для IList
, получая доступ к элементам по индексу и начиная непосредственно с индекса n вместо повторения и отбрасывания первого n элементов.
ToArray
/ ToList
также можно оптимизировать для ICollection
, используя свойство Count
для более эффективного распределения памяти.
ToDictionary
может оптимизировать для ICollection
и ICollection
, используя свойство Count
для более эффективного распределения памяти.
Попробуйте .NET Reflector . Это отличный инструмент для просмотра библиотек классов, у него есть мощный декомпилятор, который позволяет вам просматривать исходный код практически в том виде, в каком он был написан.
например. Метод расширения Count ()
реализован следующим образом
if (source == null)
{
throw Error.ArgumentNull("source");
}
ICollection<TSource> is2 = source as ICollection<TSource>;
if (is2 != null)
{
return is2.Count;
}
ICollection is3 = source as ICollection;
if (is3 != null)
{
return is3.Count;
}
int num = 0;
using (IEnumerator<TSource> enumerator = source.GetEnumerator())
{
while (enumerator.MoveNext())
{
num++;
}
}
return num;
В случае, если источник не реализует интерфейс сбора, вам придется посчитать, чтобы получить фактический счет. Просмотр кода таким образом - отличный способ учиться.