list.count是否在物理上迭代列表以对其进行计数,或者它是否保留指针

时间:2014-07-01 18:52:44

标签: c# .net vb.net performance memory-management

我正在逐步查看大量的对象,以便对列表中的所述对象进行一些操作。

在我的迭代过程中,我会根据某些标准从列表中删除一些对象。

完成所有操作后,我需要更新有关列表中对象数量的UI。 (T列表)。

问题:

  

当我调用list.count时,.net实际上遍历列表   计算它,还是将计数存储为属性/变量?

如果.net在列表中进行物理重新迭代,我也可以通过列表在我自己的迭代中保留一个计数器,并节省开销?

由于

5 个答案:

答案 0 :(得分:18)

它只是保留一个内部int来跟踪项目数。所以没有迭代。 文档说检索Count是一个O(1)操作:

http://msdn.microsoft.com/en-us/library/27b47ht3%28v=vs.110%29.aspx

你可以亲眼看看:

http://referencesource.microsoft.com/#mscorlib/system/collections/generic/list.cs

答案 1 :(得分:7)

List作为数组列表实现,它跟踪自己的大小,因此调用.Count属性不需要任何迭代。

如果你调用LINQ .Count()扩展方法,这将检查基础IEnumerable<>是否实现ICollectionList<>做了什么),并使用{{1如果可能,该接口上的属性。所以这不会导致任何迭代发生。

顺便提一下,如果您在迭代中尝试从列表中删除项目时,还会遇到其他问题。当你从迭代器中删除元素时,迭代应该如何表现并不是很清楚,所以.Count s将完全避免这个问题,如果列表自创建枚举器以来已被修改则抛出异常

答案 2 :(得分:3)

您可以使用反编译器(例如可自由使用的ILSpy)来回答这些问题。如果您引用的是List<T>类型,则Count获取者只需阅读字段:

public int Count
{
    get { return this._size; }
}

答案 3 :(得分:1)

如备注标签下所述 http://msdn.microsoft.com/en-us/library/27b47ht3(v=vs.110).aspx

检索此属性的值是O(1)操作。

这意味着没有发生迭代。

答案 4 :(得分:1)

您使用vb.net和c#标记了您的问题,因此在回复&#34;如果.net物理地重新遍历列表,我也可以在我自己的迭代中通过列表保留一个计数器,并节省开销?&#34;

如果您的迭代使用For i = first To last,则VB.NET会在进入循环时评估firstlast

Dim first As Integer = 1
Dim last As Integer = 3
For i = first To last
    Console.Write(i.ToString() & " ")
    last = -99
Next

输出:1 2 3

如果您在C#中执行等效操作,则会在每次迭代时评估firstlast

int first = 1;
int last = 1;
for (int i = first; i <= last; i++)
{
    Console.Write(i.ToString() + " ");
    last = -99;
}

输出:1

如果您的.Count()函数/属性评估成本高昂且/或者您不希望在每次迭代时重新评估它(出于其他原因),那么在C#中您可以将其分配给一个临时变量。