Подтвердить что ты не робот

Является ли <Collection>.Count дорогим для использования?

Я пишу метод кэширования, который выглядит примерно так:

while ( myHashSet.Count > MAX_ALLOWED_CACHE_MEMBERS )
{
    EjectOldestItem( myHashSet );
}

Мой вопрос о том, как определяется Count: это просто a private или protected int, или он вычисляется путем подсчета элементов каждый раз при его вызове?

4b9b3361

Ответ 1

Из http://msdn.microsoft.com/en-us/library/ms132433.aspx:

Получение значения этого свойства является операцией O (1).

Это гарантирует, что доступ к Count не будет проходить по всей коллекции.


Изменить: как и многие другие плакаты, IEnumerable<...>.Count(), как правило, не гарантируется O (1). Используйте с осторожностью!

IEnumerable<...>.Count() - это метод расширения, определенный в System.Linq.Enumerable. Текущая реализация делает явный тест, если подсчитанный IEnumerable<T> действительно является экземпляром ICollection<T> и использует, если это возможно, ICollection<T>.Count. В противном случае он пересекает IEnumerable<T> (возможно, делает ленивую оценку расширяемой) и подсчитывает элементы один за другим.

Однако я не нашел в документации, гарантировал ли он, что IEnumerable<...>.Count() использует O (1), если это возможно, я только проверил реализацию в .NET 3.5 с Reflector.


Необходимое позднее добавление: многие популярные контейнеры не получены из Collection<T>, но тем не менее их свойство Count равно O (1) (то есть не будет перебирать всю коллекцию). Примерами являются HashSet<T>.Count (это, скорее всего, то, о чем хотел спросить OP), Dictionary<K, V>.Count, LinkedList<T>.Count, List<T>.Count, Queue<T>.Count, Stack<T>.Count и т.д.

Все эти коллекции реализуют ICollection<T> или просто ICollection, поэтому их Count представляет собой реализацию ICollection<T>.Count (или ICollection.Count). Для реализации ICollection<T>.Count не требуется выполнение операции O (1), но те, о которых говорилось выше, делают это в соответствии с документацией.

(Обратите внимание: некоторые контейнеры, например Queue<T>, реализуют не общие ICollection, но не ICollection<T>, поэтому они "наследуют" свойство Count только от ICollection.)

Ответ 2

В вашем вопросе не указан конкретный класс Collection, поэтому...

Это зависит от класса Collection. ArrayList имеет внутреннюю переменную, которая отслеживает счет, как и List. Однако это специфичная реализация, и в зависимости от типа коллекции она теоретически может быть пересчитана при каждом вызове.

Ответ 4

Как отмечали другие, граф поддерживается при изменении коллекции. Это почти всегда относится к каждому типу коллекции в рамках. Это значительно отличается от использования метода расширения Count в IEnumerable, который будет перечислять коллекцию каждый раз.

Кроме того, с новыми классами коллекций свойство Count не является виртуальным, что означает, что дрожание может встроить вызов в счетчик доступа, что делает его практически таким же, как доступ к полю. Другими словами, очень быстро.

Ответ 5

В случае HashSet это просто внутреннее поле int и даже SortedSet (двоичный древовидный набор для .net 4) имеет свой счет во внутреннем поле.

Ответ 6

Согласно Reflector, он реализован как

public int Count{ get; }

поэтому он определяется производным типом

Ответ 7

Просто быстро. Будьте уверены, что есть два способа подсчета коллекции в .NET 3.5 при использовании System.Linq. Для обычной коллекции первым выбором должно быть использование свойства Count, по причинам, уже описанным в других ответах.

Также доступен альтернативный метод с помощью метода расширения LINQ.Count(). Интригующая вещь о .Count() заключается в том, что ее можно вызывать на ЛЮБОЙ перечислимый, независимо от того, реализует ли класс класса ICollection или нет, или имеет свойство Count. Если вы когда-либо звоните .Count(), имейте в виду, что он будет выполнять итерацию по коллекции, чтобы динамически генерировать счет. Это обычно приводит к сложности O (n).

Единственная причина, по которой я хотел это отметить, - использовать IntelliSense, часто бывает легко случайно использовать расширение Count(), а не свойство Count.

Ответ 8

Это внутренний int, который увеличивается при каждом добавлении нового элемента в коллекцию.