If I have the following IEnumerable list which comes from some repository.
IEnumerable<SomeObject> items = _someRepo.GetAll();
What is faster:
items.Count(); // Using Linq on the IEnumerable interface.
or
List<SomeObject> temp = items.ToList<SomeObject>(); // Cast as a List
temp.Count(); // Do a count on a list
Is the Linq
Count()
faster or slower than casting the IEnumerable
to a List
and then performing a Count()
?
Update: Improved the question a little bit to a bit more realistic scenario.
Calling Count
directly is a better choice.
Enumerable.Count
has some performance improvements built in that will let it return without enumerating the entire collection:
public static int Count<TSource>(this IEnumerable<TSource> source) {
if (source == null) throw Error.ArgumentNull("source");
ICollection<TSource> collectionoft = source as ICollection<TSource>;
if (collectionoft != null) return collectionoft.Count;
ICollection collection = source as ICollection;
if (collection != null) return collection.Count;
int count = 0;
using (IEnumerator<TSource> e = source.GetEnumerator()) {
checked {
while (e.MoveNext()) count++;
}
}
return count;
}
ToList()
uses similar optimizations, baked into List<T>(IEnumerable<T> source)
constructor:
public List(IEnumerable<T> collection) {
if (collection==null)
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection);
Contract.EndContractBlock();
ICollection<T> c = collection as ICollection<T>;
if( c != null) {
int count = c.Count;
if (count == 0)
{
_items = _emptyArray;
}
else {
_items = new T[count];
c.CopyTo(_items, 0);
_size = count;
}
}
else {
_size = 0;
_items = _emptyArray;
// This enumerable could be empty. Let Add allocate a new array, if needed.
// Note it will also go to _defaultCapacity first, not 1, then 2, etc.
using(IEnumerator<T> en = collection.GetEnumerator()) {
while(en.MoveNext()) {
Add(en.Current);
}
}
}
}
But as you can see it only uses generic ICollection<T>
, so if your collection implements ICollection
but not its generic version calling Count()
directly will be much faster.
Not calling ToList
first also saves you an allocation of new List<T>
instance - not something overly expensive, but it's always better to avoid unnecessary allocation when possible.