【问题标题】:How can I get the "actual" count of element in a IEnumerable?如何获得 IEnumerable 中元素的“实际”计数?
【发布时间】:2012-07-18 16:48:33
【问题描述】:

如果我写了:

for (int i = 0; i < Strutture.Count(); i++)
{
}

而 Strutture 是一个具有 200 个元素的 IEnumerable,IIS 崩溃。那是因为我每次执行Strutture.Count() 时都会看到它执行与该 IEnumerable 链接的所有 LINQ 查询。

那么,我怎样才能获得“当前”的元素数量?我需要一份清单吗?

【问题讨论】:

  • 是时候试试foreach

标签: linq ienumerable


【解决方案1】:

“这是因为我每次执行 Strutture.Count() 时都会看到它执行与该 IEnumerable 链接的所有 LINQ 查询。”

不这样做,它怎么知道有多少元素?

例如:

Enumerable.Range(0,1000).Where(i => i % 2==0).Skip(100).Take(5).Count();

不执行 LINQ,你怎么知道有多少元素?

如果您想知道源中有多少元素(例如 Enumerable.Range),那么我建议您使用对该源的引用并直接查询它。例如

 var numbers = Enumerable.Range(0,1000);
 numbers.Count();

另外请记住,一些数据源并没有真正的“计数”概念,或者如果他们这样做,则需要遍历每一个项目并对其进行计数。

最后,如果您重复使用 .Count() [并且您不希望值实际改变],缓存可能是个好主意:

 var count = numbers.Count();
 for (int i =0; i<count; i++) //  Do Something

补充:

“在第一次 Count() 时,执行 LINQ 查询。接下来,它只是“检查”值 :) 而不是“再次执行 LINQ 查询...”:)” - Markzzz

那我们为什么不这样做呢?

var query = Enumerable.Range(0,1000).Where(i => i % 2==0).Skip(100).Take(5).Count();
var result = query.ToArray() //Gets and stores the result!
result.Length;   

:)

“但是当我执行第一个“计数”时,它应该存储(在 LINQ 查询之后)新的 IEnumerable(状态已更改)。如果我再次执行 .Count(),为什么 LINQ 需要再次执行所有查询。” - Markzzz

因为您正在创建一个查询,它会被编译成 X、Y、Z。您运行相同的查询两次,但结果可能会有所不同。

例如,看看这个:

    static void Main(string[] args)
    {
        var dataSource = Enumerable.Range(0, 100).ToList();
        var query = dataSource.Where(i => i % 2 == 0);

        //Run the query once and return the count:
        Console.WriteLine(query.Count());  //50

        //Now lets modify the datasource - remembering this could be a table in a db etc.
        dataSource.AddRange(Enumerable.Range(100, 100));

        //Run the query again and return the count:
        Console.WriteLine(query.Count());  //100
        Console.ReadLine();
    }

这就是为什么我建议存储上面的查询结果!

【讨论】:

  • "不这样做,怎么知道有多少元素?" : 用逻辑,我是这么想的。在第一个 Count() 中,执行 LINQ 查询。然后,对于下一个,它只是“检查”值 :) 而不是“再次执行 LINQ 查询......”:)
  • 有逻辑吗?将 '(i => i % 2==0)' 替换为 '(i => i == Random.Next())' 看看你的逻辑能走多远:P 鉴于你的评论,听起来你应该缓存您的查询结果 - 我将添加一个示例。
  • 但是当我执行第一个“计数”时,它应该存储(在 LINQ 查询之后)新的 IEnumerable(状态已更改)。如果我再次执行 .Count(),为什么 LINQ 需要再次执行所有查询。它应该在第一个 Count() 和第二个 Count() 之间执行查询,其中数据应该被更改。这是我的逻辑:)
  • 是的,事实上考虑“更新”数据库,这是有道理的 :) 谢谢你的澄清!
  • P.S. AddRange 它是在第二个 Count() 处执行还是立即执行?
【解决方案2】:

具体化数字:

int number = Strutture.Count();
for (int i = 0; i < number; i++)
{
}

实现列表:

var list = Strutture.ToList();
for (int i = 0; i < list.Count; i++)
{
}

或使用foreach

foreach(var item in Strutture)
{   
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-17
    • 2019-03-16
    相关资源
    最近更新 更多