Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is <Collection>.Count Expensive to Use?

I'm writing a cache-eject method that essentially looks like this:

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

My question is about how Count is determined: is it just a private or protected int, or is it calculated by counting the elements each time its called?

like image 942
Bob Kaufman Avatar asked Feb 26 '10 20:02

Bob Kaufman


1 Answers

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

Retrieving the value of this property is an O(1) operation.

This guarantees that accessing the Count won't iterate over the whole collection.


Edit: as many other posters suggested, IEnumerable<...>.Count() is however not guaranteed to be O(1). Use with care!

IEnumerable<...>.Count() is an extension method defined in System.Linq.Enumerable. The current implementation makes an explicit test if the counted IEnumerable<T> is indeed an instance of ICollection<T>, and makes use of ICollection<T>.Count if possible. Otherwise it traverses the IEnumerable<T> (possible making lazy evaluation expand) and counts items one by one.

I've not however found in the documentation whether it's guaranteed that IEnumerable<...>.Count() uses O(1) if possible, I only checked the implementation in .NET 3.5 with Reflector.


Necessary late addition: many popular containers are not derived from Collection<T>, but nevertheless their Count property is O(1) (that is, won't iterate over the whole collection). Examples are HashSet<T>.Count (this one is most likely what the OP wanted to ask about), Dictionary<K, V>.Count, LinkedList<T>.Count, List<T>.Count, Queue<T>.Count, Stack<T>.Count and so on.

All these collections implement ICollection<T> or just ICollection, so their Count is an implementation of ICollection<T>.Count (or ICollection.Count). It's not required for an implementation of ICollection<T>.Count to be an O(1) operation, but the ones mentioned above are doing that way, according to the documentation.

(Note aside: some containers, for instance, Queue<T>, implement non-generic ICollection but not ICollection<T>, so they "inherit" the Count property only from from ICollection.)

like image 165
Vlad Avatar answered Sep 16 '22 18:09

Vlad