可枚举.跳过和排序

本文关键字:排序 枚举 | 更新日期: 2023-09-27 18:32:06

所以IEnumerable不能保证顺序。

这是否意味着如果您这样做myEnumerable.Skip(5)您不能(除非您.ToList()或之前这样做)保证将退回什么?

可枚举.跳过和排序

一旦对象被IEnumerator产生,它们就会有一个顺序。 有些项目先出来,有些项目排在第二位,等等。 对于某些特定的实现,顺序可能有意义,对于其他实现,它可能是任意的,但仍然存在一些顺序。 Skip实现很简单;它获得许多物品而不产生它们,然后获得其余的并产生它们。 跳过的项目是否具有任何特殊意义是调用该方法的人的责任。

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

特定排序是否由任何特定IEnumerable<T>保证

取决于
  • 该特定实现是如何完成的,以及
  • 基础集合/类的语义。

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

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

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

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

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

IEnumerable 是一个接口。因此,接口无法保证顺序。但是,如果您有一个实现该接口的实际对象,则该对象可能(并且经常)保证顺序。

如果使用Skip(x),前x元素将被忽略,之后的所有内容都将以新的IEnumerable<T>返回。该接口不保证它会保持秩序,但实际上它确实如此。每当您在IEnumerable<T>上操作时,它实际上都会以线性方式通过相同的列表。例如,如果您逐行读取文件并IEnumerable<T>则这些行将始终与它们在文件中的顺序相同(假设您不使用排序方法)。即使您使用 Where 或其他方法来筛选结果,订单仍将保留。您唯一需要担心的是实现IEnumerable<T>的自定义集合。.NET 中的集合将按预期运行。