当前位置:  开发笔记 > 编程语言 > 正文

从IEnumerable <T>计算项目而不迭代?

如何解决《从IEnumerable<T>计算项目而不迭代?》经验,为你挑选了9个好方法。

IEnumerable不支持这个.这是设计的.IEnumerable在您需要之前使用延迟评估来获取您要求的元素.

如果你想知道项目的数量,而不是迭代它们你可以使用ICollection,它有一个Count属性.



1> Mendelt..:

IEnumerable不支持这个.这是设计的.IEnumerable在您需要之前使用延迟评估来获取您要求的元素.

如果你想知道项目的数量,而不是迭代它们你可以使用ICollection,它有一个Count属性.


如果您不需要通过索引器访问列表,我更喜欢ICollection而不是IList.
@Shimmy你迭代并计算元素.或者从Linq命名空间调用Count()来为您执行此操作.
我通常只是习惯于抓住List和IList.但特别是如果你想自己实现ICollection更容易,并且还有Count属性.谢谢!

2> Daniel Earwi..:

System.Linq.Enumerable.Count对扩展方法IEnumerable有以下实现:

ICollection c = source as ICollection;
if (c != null)
    return c.Count;

int result = 0;
using (IEnumerator enumerator = source.GetEnumerator())
{
    while (enumerator.MoveNext())
        result++;
}
return result;

所以它试图转换为ICollection具有Count属性的属性,并在可能的情况下使用它.否则它会迭代.

因此,最好的Count()办法是在IEnumerable对象上使用扩展方法,因为这样可以获得最佳性能.


非常有趣的是它首先尝试强制转换为"ICollection ".
@Jaider - 比这稍微复杂一点.`IEnumerable `继承`IDisposable`,它允许`using`语句自动处理它.`IEnumerable`没有.因此,如果你以任何一种方式调用`GetEnumerator`,你应该以`var d = e作为IDisposable完成; if(d!= null)d.Dispose();`

3> Robert Pauls..:

只需添加额外的一些信息:

Count()扩展并不总是迭代.考虑Linq to Sql,其中计数进入数据库,但不是返回所有行,而是发出Sql Count()命令并返回该结果.

此外,编译器(或运行时)足够智能,Count()如果有一个对象方法,它将调用它.所以它并不像其他响应者所说的那样,完全无知并且总是为了计算元素而迭代.

在许多情况下,程序员只是if( enumerable.Count != 0 )使用Any()扩展方法进行检查,因为if( enumerable.Any() ) linq的惰性评估效率更高,因为一旦确定有任何元素,它就会短路.它也更具可读性


+1 for.任何用于测试没有元素的
关于集合和数组。如果您碰巧使用了集合,请使用`.Count`属性,因为它始终知道其大小。查询`collection.Count`时,没有额外的计算,它只返回已知的计数。据我所知,与Array.length相同。但是,.Any()使用(IEnumerator <TSource> enumerator = source.GetEnumerator())获取源的枚举,如果可以执行enumerator.MoveNext(),则返回true。对于集合:“ if(collection.Count> 0)”,数组:“ if(array.length> 0)”,对于可枚举,则执行“ if(collection.Any())”。

4> Joel Coehoor..:

我的一位朋友有一系列博客文章,说明了为什么你不能这样做.他创建了返回IEnumerable的函数,其中每次迭代返回下一个素数,一直到ulong.MaxValue,并且在您要求之前不会计算下一个项目.快速流行问题:返回了多少项?

这是帖子,但它们有点长:

    Beyond循环(提供其他帖子中使用的初始EnumerableUtility类)

    迭代的应用(初始实现)

    疯狂扩展方法:ToLazyList(性能优化)


我真的希望MS已经定义了一种方法来让enumerables描述他们对自己的看法("不知道任何事情"是一个有效的答案).没有任何困难可以回答诸如"你知道自己是有限的"这样的问题,"你知道自己是少于N个元素的有限",以及"你知道自己是无限的",因为任何可以枚举的人都可以合理地(如果没有帮助)对所有人回答"否".如果有一个标准的方法可以提出这样的问题,那么对于普查员来说,返回无穷无尽的序列会更安全......

5> Chris Ammerm..:

没有迭代,IEnumerable不能计数.

在"正常"情况下,实现IEnumerable或IEnumerable 的类(例如List )可以通过返回List .Count属性来实现Count方法.但是,Count方法实际上不是在IEnumerable 或IEnumerable接口上定义的方法.(事实上​​,唯一的一个是GetEnumerator.)这意味着无法为它提供特定于类的实现.

相反,Count它是一个扩展方法,在静态类Enumerable上定义.这意味着它可以在IEnumerable 派生类的任何实例上调用,而不管该类的实现如何.但它也意味着它在一个地方实施,在任何这些类之外.这当然意味着它必须以完全独立于这些类的内部的方式实现.唯一这样的计数方法是通过迭代.



6> 小智..:

或者,您可以执行以下操作:

Tables.ToList().Count;



7> JesperE..:

不,不是一般的.使用枚举的一点是,枚举中的实际对象集是未知的(事先,甚至根本不知道).



8> prosseek..:

您可以使用System.Linq.

using System;
using System.Collections.Generic;
using System.Linq;

public class Test
{
    private IEnumerable Tables
    {
        get {
             yield return "Foo";
             yield return "Bar";
         }
    }

    static void Main()
    {
        var x = new Test();
        Console.WriteLine(x.Tables.Count());
    }
}

你会得到结果'2'.


这不适用于非泛型变体IEnumerable(没有类型说明符)

9> Samuel Jack..:

超越您的直接问题(已经完全回答了否定),如果您希望在处理可枚举时报告进度,您可能需要查看我的博客帖子报告Linq查询期间的进度.

它可以让你这样做:

BackgroundWorker worker = new BackgroundWorker();
worker.WorkerReportsProgress = true;
worker.DoWork += (sender, e) =>
      {
          // pretend we have a collection of 
          // items to process
          var items = 1.To(1000);
          items
              .WithProgressReporting(progress => worker.ReportProgress(progress))
              .ForEach(item => Thread.Sleep(10)); // simulate some real work
      };

推荐阅读
和谐啄木鸟
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有