所以IEnumerable
不保证顺序。
这是否意味着如果你这样做,myEnumerable.Skip(5)
你不能(除非你这样做.ToList()
或之前)保证会退还什么?
一旦对象被 an 产生,IEnumerator
它们确实有一个顺序。有一些项目首先出现,一些项目随后出现,依此类推。对于某些特定的实现,顺序可能有意义,对于其他实现,它可能是任意的,但仍然有一些顺序。Skip
实现很简单;它得到了许多项目而不产生它们,然后得到其余的并产生它们。跳过的项目是否有任何特殊意义是调用该方法的人的责任。
调用ToList
永远不会改变序列中项目的顺序,所以在调用之前添加这样的调用Skip
不会改变任何东西。OrderBy
另一方面,调用将导致更改顺序,可能从无意义的顺序变为有意义的顺序。这并不是说它是必需的,只是在某些情况下它可以成为有用的工具。
任何特定的是否保证特定的排序IEnumerable<T>
取决于
数组将以明显的顺序(从x[0]
到x[n]
)枚举其内容。a 同上List<T>
,它本质上是一个长度可调的数组。当然,实际的 [链接] 列表只能按顺序枚举。
Dictionary<K,V>
, , 二叉树等的枚举顺序HashSet<T>
取决于添加对象的顺序。将具有不同顺序的相同值集合添加到二叉树中,由此构建的树的结构会有所不同(退化的情况,当然是当对象按顺序添加时,在这种情况下,树结构会折叠成 [ordered ] 链表。
话虽IEnumerable<T>
如此,除非对基础集合进行任何修改,否则 , 的任何特定实例在每次枚举时都会产生相同的值序列。当然,这假设接口的合理实现。如果界面通过随机洗牌来枚举集合,当然,所有的赌注都是关闭的。
如果生产的物品的实际顺序很重要,您需要
如果使用Skip(x)
,第一个x
元素将被忽略,之后的所有内容都将返回一个新的IEnumerable<T>
. 该接口不保证它会保持顺序,但实际上它确实如此。任何时候你对它进行操作时,IEnumerable<T>
它实际上都会以线性方式通过同一个列表。例如,如果您逐行读取文件,并且IEnumerable<T>
这些行将始终与它们在文件中的顺序相同(假设您不使用排序方法)。即使您使用某种Where
或其他方法来过滤结果,仍然会保留顺序。您唯一需要担心的是实现IEnumerable<T>
. .NET 中的集合将按照您期望的方式运行。
IEnumerable 是一个接口。因此,接口不能保证顺序。但是,如果您有一个实现该接口的实际对象,则该对象可能(并且通常会)保证顺序。