代码之家  ›  专栏  ›  技术社区  ›  balalakshmi

IEnumerable Count()和长度之间的差异

  •  57
  • balalakshmi  · 技术社区  · 16 年前

    两者的主要区别是什么 IEnumerable Count() Length ?

    3 回复  |  直到 7 年前
        1
  •  83
  •   Levi Botelho    13 年前

    通过调用count on IEnumerable<T> 我假设你指的是扩展方法 Count System.Linq.Enumerable . Length 不是上的方法 IEnumerable<t> 而是.NET中数组类型的属性,例如 int[] .

    区别在于性能。这个 长度 属性保证为O(1)操作。的复杂性 伯爵 扩展方法因对象的运行时类型而异。它将尝试强制转换为多个支持O(1)长度查找的类型,例如 ICollection<T> 通过A 伯爵 财产。如果没有可用的项目,那么它将枚举所有项目并计算其复杂性为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)
    

    价值 e2 实现为不支持O(1)计数的C迭代器,因此该方法 伯爵 必须枚举整个集合以确定它的长度。

        2
  •  20
  •   Erick Brown    7 年前

    除了 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;
    }
    

    .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;
    }
    
        3
  •  1
  •   Erik Hart    14 年前
    • 长度是固定属性,例如一维数组或字符串。所以没有必要进行计数操作(多维数组的大小是所有维度的乘积)。o(1)这里的操作意味着检索时间总是相同的,不管有多少个元素。线性搜索(与此相反)是O(N)。

    • ICollections上的Count属性(例如,List和List<t>)可能会更改,因此必须在执行添加/删除操作时更新该属性,或者在集合更改后请求计数时更新该属性。取决于对象的实现。

    • linq的count()方法在每次调用时基本上都会迭代(除非对象是ICollection类型,然后请求ICollection.Count属性)。

    注意,IEnumerable通常不是已经定义的对象集合(如列表、数组、哈希表等),而是链接到后台操作,后台操作在请求时生成结果(称为延迟执行)。

    通常,您有这样一个类似SQL的LINQ语句(延迟执行的典型应用程序):

    IEnumerable<Person> deptLeaders = 
       from p in persons
       join d in departments
          on p.ID equals d.LeaderID
       orderby p.LastName, p.FirstName
       select p;
    

    然后,有这样的代码:

    if (deptLeaders.Count() > 0)
    {
       ReportNumberOfDeptLeaders(deptLeaders.Count());
       if (deptLeaders.Count() > 20)
          WarnTooManyDepartmentLeaders(deptLeaders.Count());
    }
    

    因此,当对太多的部门领导发出警告时,.NET会对这些人进行四次检查,与部门领导进行对比,按名称对其进行排序,然后对结果对象进行计数。

    只有当人员和部门是预设值集合时,才需要进行查询。

    推荐文章