【问题标题】:IEnumerable and orderIEnumerable 和 order
【发布时间】:2012-05-02 08:04:49
【问题描述】:

我对@9​​87654321@中的订单有疑问。

据我所知,遍历 IEnumerable 是伪代码,可以用以下方式编写:

while (enumerable.HasNext())
{
    object obj = enumerable.Current;
    ...
}

现在,假设需要对排序集合进行操作。在这种情况下可以使用 IEnumerable 还是尝试其他支持索引的方法(即IList)更好?

换句话说:IEnumerable 的合同是否对订单做出任何保证?

因此,IEnumerable 不是保证排序的通用接口的正确含义。新的问题是什么接口或类应该用于不可变集合的顺序? ReadonlyCollection? IList?两者都包含Add()方法(甚至前者没有实现)。

我自己的想法:IEnumerable 不提供任何关于订购的保证。正确的实现可以在不同的枚举中以不同的顺序返回相同的元素(考虑 SQL 查询)

我知道 LINQ First(),但是如果 IEnumerable 没有说明它的排序,那么这个扩展就毫无用处了。

【问题讨论】:

    标签: c# .net collections ienumerable


    【解决方案1】:

    IEnumerable/IEnumerable<T> 不保证排序,但使用 IEnumerable/IEnumerable<T> 的实现可能会或可能不保证排序。

    例如,如果您枚举List<T>,则可以保证顺序,但如果您枚举HashSet<T>,则不提供此类保证,但两者都将使用IEnumerable<T>接口枚举。

    【讨论】:

    • 另一个例子是Dictionary<,>。清楚地记录了枚举其条目的顺序是未定义的。所以像dict.Last().Key 这样的代码(其中dictDictionary<,>Last() 是LINQ 扩展方法)没有意义。 (我听说一位开发人员正是这样做的。)
    • 我要补充一点,已经说过正确理解某些通用集合的顺序保证是很重要的。所以顺序保证不是关于特定的顺序(例如,作为排序的结果),而是关于保证同一集合的元素的顺序对于后续枚举是相同的。大多数收藏品都没有明确保证这一点。 IList 只表示一种以键为索引的字典。
    • IOrderedEnumerable 可能表明该集合保证了顺序(尽管接口仍然没有),但它超出了我们的需要 - 它通常代表特定的 SORT 顺序,而我们需要 ANY (随机)顺序,仅在枚举之间得到保证。总而言之,只有具体的实现才能真正保证顺序(例如Array,List)。
    • 在主题中描述的情况下(返回的集合),实际上应该向用户显示什么类型的集合并没有任何区别(除非您想更明确地声明您的合同),您只需要实际返回的类型即可提供该订购保证。
    • List<T>的情况下,枚举顺序是否得到保证?你怎么知道的?
    【解决方案2】:

    实施细节。 IEnumerable 将枚举该项目 - 如何实施取决于实施。 MOST 列表等按照其自然顺序运行(索引 0 向上等)。

    IEnumerable 的合同在一般情况下是否保证我们有一些订单?

    不,它只保证枚举(每个项目一次等)。 IEnumerable 没有保证顺序,因为它也可用于无序项。

    我知道 LINQ First(),但是如果 IEnumerable 没有说明它的顺序,那么这个扩展就没什么用了。

    不,不是,因为你可能有内在的秩序。您以 SQL 为例 - 结果是一个 IEnumerable,但如果我之前强制执行了排序(通过使用 OrderBy()),那么 IEnumerable 是根据 LINQ 的定义进行排序的。 AsEnumerable().First() 得到我,然后是 Order 的第一项。

    【讨论】:

      【解决方案3】:

      也许您正在寻找IOrderedEnumerable 接口?它由OrderBy() 等扩展方法返回,并允许使用ThenBy() 进行后续排序。

      【讨论】:

      • 不幸的是,如果你想接受像 IList 这样的接口,它可以保证订单但不从 IOrderedEnumerable 继承,这将不起作用。见stackoverflow.com/q/5429974/1157054
      【解决方案4】:

      你混合了两点:枚举和排序。

      当您枚举 IEnumerable 时,您不应该关心顺序。您使用接口,它的实现应该关心顺序。

      例如:

      void Enumerate(IEnumerable sequence)
      {
          // loop
      }
      
      SortedList<T> sortedList = ...
      Enumerate (sortedList);
      

      在方法内部它仍然是一个固定顺序的列表,但方法不知道具体的接口实现,它的特殊性。

      【讨论】:

      • 不要混合排序和排序。 SortedList 按键顺序存储项目,但 OP 可能需要一些其他任意顺序
      猜你喜欢
      • 1970-01-01
      • 2019-03-17
      • 2016-03-29
      • 2018-06-30
      • 1970-01-01
      • 2011-06-25
      • 1970-01-01
      • 1970-01-01
      • 2018-05-17
      相关资源
      最近更新 更多