Enumerable.Skip和订购

时间:2013-09-19 16:49:06

标签: c# linq

所以IEnumerable不保证订单。

这是否意味着如果你做myEnumerable.Skip(5)你不能(除非你.ToList()或以前做过)保证将返回什么?

4 个答案:

答案 0 :(得分:5)

一旦对象由IEnumerator产生,他们就会有订单。首先出现一些项目,然后出现一些项目,等等。对于某些特定的实现,订单可能有意义,对于其他项目,它可能是任意的,但仍然存在一些顺序。 Skip实施很简单;它得到了许多物品而没有产生它们,然后得到其余的并产生它们。跳过的项目是否意味着特别是任何调用该方法的人的责任。

调用ToList永远不会更改序列中项目的顺序,因此在调用Skip之前添加此类调用不会改变任何内容。另一方面,对OrderBy的调用将导致更改的顺序,可能从无意义的顺序到有意义的顺序。这并不是说它是必需的,只是它在某些情况下可以成为一种有用的工具。

答案 1 :(得分:3)

任何特定IEnumerable<T>是否保证特定排序取决于

  • 该特定实施是如何完成的,以及
  • 底层集合/类的语义。

数组将以明显的顺序(从x[0]x[n]枚举其内容。)同样为List<T>,它本质上是一个可调整长度的数组。当然,实际[链接]列表只能按顺序枚举。

Dictionary<K,V>HashSet<T>,二叉树等的枚举顺序取决于添加对象的顺序。将具有不同排序的相同值集合添加到二叉树中,并且由此构造的树的结构将变化(当然,退化情况是当按顺序添加对象时,在这种情况下,树结构折叠成[有序] ]链表。

话虽如此,IEnumerable<T>的任何特定实例,除非对基础集合进行任何修改,否则每次枚举时都会产生相同的值序列。当然,这假设是接口的合理实现。如果接口通过随机随机播放来枚举集合,当然,所有赌注都会关闭。

如果生成的项目的实际顺序很重要,则需要

  • 使用具有所需语义的集合,或
  • 通过对集合或枚举进行排序来强制执行所需的排序。

答案 2 :(得分:0)

如果您使用Skip(x),则会忽略第一个x元素,之后的所有内容都将以新的IEnumerable<T>返回。界面不保证它会保留顺序,但实际上它确实如此。无论何时操作IEnumerable<T>,它实际上都会以线性方式通过相同的列表。例如,如果你逐行读取文件和IEnumerable<T>,那么这些行的顺序与它们在文件中的顺序相同(假设你没有使用排序方法)。即使您使用Where或其他方法过滤结果,订单仍会保留。您唯一需要担心的是实现IEnumerable<T>的自定义集合。 .NET中的集合将按照您的预期运行。

答案 3 :(得分:0)

IEnumerable是一个接口。因此,界面无法保证订单。但是,如果您有一个实现该接口的实际对象,则该对象可能(并且通常会)保证订单。