views:

1192

answers:

2

What are the key differences between IEnumerable Count() and Length?

+6  A: 

By calling Count on IEnumerable<T> I'm assuming you're referring to the extension method Count on System.Linq.Enumerable. Length is not a method on IEnumerable<T> but rather a property on array types in .Net such as int[].

The difference is performance. TheLength property is guaranteed to be a O(1) operation. The complexity of the Count extension method differs based on runtime type of the object. It will attempt to cast to several typse which support O(1) length lookup like ICollection<T> via a Count property. If none are available then it will enumerate all items and count them which has a complexity of O(N).

For example

int[] list = CreateSomeList();
Console.WriteLine(list.Length);  // O(1)
IEnumerable<int> e1 = list;
Console.WriteLine(e1.Count()); // O(1) 
IEnumerable<int> e2 = list.Where(x => x <> 42);
Console.WriteLine(e2.Count()); // O(N)

The value e2 is implemented as a C# iterator which does not support O(1) counting and hence the method Count must enumerate the entire collection to determine how long it is.

JaredPar
`List<T>` doesn't have a Length property - it has a Count property. Arrays have a `Length` though. `Count` is specified in `ICollection` and `ICollection<T>` (which `IList<T>` extends).
Jon Skeet
@Jon, doh. Going to blame lack of sleep here. Will update
JaredPar
And if your `IEnumerable<T>` is infinitely-long, `Count()` will never return...
Roger Lipscombe
+2  A: 

Little addition to Jon Skeet's comment.

There are source code of Count() extension method:

.NET 3:

public static int Count<TSource>(this IEnumerable<TSource> source)
{
    if (source == null)
    {
        throw Error.ArgumentNull("source");
    }
    ICollection<TSource> is2 = source as ICollection<TSource>;
    if (is2 != null)
    {
        return is2.Count;
    }
    int num = 0;
    using (IEnumerator<TSource> enumerator = source.GetEnumerator())
    {
        while (enumerator.MoveNext())
        {
            num++;
        }
    }
    return num;
}

.NET 4:

public static int Count<TSource>(this IEnumerable<TSource> source)
{
    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;
}
bniwredyc
Note that in .NET 4 there's another block to check for the non-generic `ICollection` type too. (As that also has a `Count` property.)
Jon Skeet
@Jon Skeet: thank you
bniwredyc