IEnumerable Count()和Length之间的差异

bal*_*hmi 60 .net c# ienumerable

IEnumerable Count()和之间的主要区别是Length什么?

Jar*_*Par 89

通过调用指望IEnumerable<T>我假设你指的是扩展方法CountSystem.Linq.Enumerable. Length不是一个方法,IEnumerable<T>而是.Net中数组类型的属性,如int[].

不同的是性能.该Length物业保证是O(1)操作.Count扩展方法的复杂性根据对象的运行时类型而不同.它将尝试转换为支持O(1)长度查找的几种类型,如ICollection<T>通过Count属性.如果没有可用的话,它将枚举所有项目并计算它们的复杂度为O(N).

例如

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)
Run Code Online (Sandbox Code Playgroud)

该值e2是作为C#迭代器实现的,它不支持O(1)计数,因此该方法Count必须枚举整个集合以确定它的持续时间.

  • `List <T>`没有Length属性 - 它有一个Count属性.数组有一个"长度".`Count`在`ICollection`和`ICollection <T>`中指定(`IList <T>`extends). (5认同)
  • 如果你的`IEnumerable <T>`是无限长的,`Count()`将永远不会返回... (4认同)

bni*_*dyc 22

Jon Skeet评论的一点点补充.

这是Count()扩展方法的源代码:

.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;
}
Run Code Online (Sandbox Code Playgroud)

.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;
}
Run Code Online (Sandbox Code Playgroud)

  • 请注意,在.NET 4中还有另一个块来检查非泛型的"ICollection"类型.(因为它也有一个`Count`属性.) (9认同)