list.count是否在物理上迭代列表以对其进行计数,或者它是否保留指针
我正逐步通过一个大的对象列表来做一些有关列表中所述对象的东西。
在迭代期间,我将根据特定条件从列表中删除一些对象。
完成所有操作后,我需要更新有关列表中对象数量的UI。 (T列表)。
题:
当我调用list.count时,.net是否实际遍历列表来计算它,还是将计数存储为属性/变量?
如果.net在列表中进行物理重新迭代,我也可以通过列表在我自己的迭代中保留一个计数器,并节省开销?
谢谢
它只是保留一个内部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
List
实现为数组列表,它跟踪自己的大小,因此调用.Count
属性不需要任何迭代。
如果调用LINQ .Count()
扩展方法,这将检查底层IEnumerable<>
是否实现ICollection
( List<>
所做的),并在可能的情况下在该接口上使用.Count
属性。 所以这不会导致任何迭代发生。
顺便提一下,如果您在迭代它时尝试从列表中删除项目,则还会遇到其他问题。 当你从迭代器中删除元素时,迭代应该如何表现并不是很清楚,因此List<>
s将完全避免这个问题,如果列表自创建枚举器以来已被修改,则抛出exception。
您可以使用反编译器(例如可自由使用的ILSpy)来回答这些问题。 如果你指的是List
类型,那么Count
getter只需要读取一个字段:
public int Count { get { return this._size; } }
如备注选项卡http://msdn.microsoft.com/en-us/library/27b47ht3(v=vs.110).aspx所述
检索此属性的值是O(1)操作。
这意味着没有发生迭代。
你用vb.net和c#标记了你的问题,所以在回答“如果.net物理地重新遍历列表时,我也可以通过列表在我自己的迭代中保留一个计数器,并节省开销?”
如果您的迭代使用For i = first To last
则VB.NET将在进入循环时first
进行评估, last
进行评估:
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#中执行等效操作,则会在每次迭代时评估first
和last
一个:
int first = 1; int last = 1; for (int i = first; i <= last; i++) { Console.Write(i.ToString() + " "); last = -99; }
输出:1
如果您的.Count()函数/属性评估起来很昂贵,并且/或者您不希望在每次迭代时重新评估它(由于某些其他原因),那么在C#中您可以将其分配给临时变量。