【问题标题】:Is iterating over a Queue<T> guaranteed to be in queue order?遍历 Queue<T> 是否保证按队列顺序排列?
【发布时间】:2013-08-29 09:22:09
【问题描述】:

这是否保证总是打印123

Queue<string> theQueue = new Queue<string>();
theQueue.Enqueue("1");
theQueue.Enqueue("2");
theQueue.Enqueue("3");
foreach(var str in theQueue)
{
    Console.Write(str);
}
Console.WriteLine();

编辑: 我完全同意以任何其他顺序枚举的队列显然是不正确的。这就是我问这个问题的原因。但是,抽象数据类型 queue 仅对其 enqueuedequeue 操作做出保证。

我正在寻找一个参考文档的答案,以保证 .NET BCL 中的这种排序。

【问题讨论】:

  • 我认为大多数人都忽略了您的问题。队列由推送和弹出的工作方式定义。在这个方法中的迭代没有在队列的正常定义中定义
  • @bengoesboom yes it is defined, Queue&lt;T&gt;.GetEnumerator() 有它自己的 MSDN 页面,包括说明foreach 调用使用的IEnumerable 的行为与Peek() 和@987654331 相同的示例代码@.
  • 您是否阅读了 Queue&lt;T&gt; 的 MSDN 页面?对我来说似乎是一个很好的参考(Queue&lt;T&gt; b = new Queue&lt;T&gt;(a) 还能如何发挥作用?)。
  • @ScottChamberlain 我指的是“队列”的抽象数据类型,而不是具体的实现
  • @bengoesboom 你说的这个抽象数据类型是什么?这就是 Queue 是什么,它的 GetEnumerator 函数有据可查

标签: .net collections base-class-library


【解决方案1】:

是的。它是。队列是先进先出的集合,会按顺序枚举。

【讨论】:

  • 这对我来说在直觉上似乎是正确的,但是有任何文档可以支持您吗?
  • Queue<T>.GetEnumerator() 页面有更好的示例代码。
【解决方案2】:

文件证明:

是的,来自MSDN Documenation of GetEnumerator,重点是我的

最初,枚举器位于集合中的第一个元素之前。在这个位置,Current 是未定义的。因此,在读取 Current 的值之前,您必须调用 MoveNext 将枚举数前进到集合的第一个元素。

Current 返回相同的对象,直到调用 MoveNext。 MoveNext 将 Current 设置为 下一个元素。

但这并没有说明集合中的第一个元素是什么。要回答这个问题,我们需要去description of Queue 本身:

表示对象的先进先出集合。

结合以上两个语句,我们有官方代码约定从枚举器返回的第一个对象将是集合中的第一个元素,而事实上集合中的第一个元素将是添加到集合中的first-in对象为我们提供最终输出,即遍历Queue&lt;T&gt; 将始终按顺序排列。


顺便说一句,将其与Dictionary 进行比较,GetEnumerator() 的定义声明了关于首先检索第一个元素的同一行。但是Dictionary's description 确实包含了集合中对象的显式排序:

表示键和值的集合。

这就是为什么Dictionary 不按插入顺序返回是“合法的”。

【讨论】:

  • Dictionary<TKey,TValue> 的文档说的完全一样,并且已经表明您不能指望字典按添加顺序枚举项目。我承认Queue&lt;T&gt; 的实现按预期工作(即按删除顺序迭代),但我坚持认为该行为只是一个实现细节:合同中没有任何内容表明它必须 这样做。
  • @JimMischel 我已经更新了我的答案,并结合了我之前(已删除)的评论。如果您仍然觉得文档没有指定代码合同,请告诉我我错过了什么。
  • 我理解您的推理,并且我认为很可能(正如我一直认为的那样)他们实际上是指指定代码合同的文档。在我看来,文档留下了一些回旋余地。我认为它应该明确说明项目是按删除顺序迭代的。但这是我应该与文档团队讨论的问题。
【解决方案3】:

这里是 MSDN 页面,它描述了 GetEnumerator for Queue。总之(正如其他人所说)你很高兴。 http://msdn.microsoft.com/en-us/library/4a9449ty.aspx

请注意,以这种方式枚举队列不会像循环调用 Dequeue() 那样更改其内容

【讨论】:

    【解决方案4】:

    是的,对Queue&lt;T&gt; 的迭代保证按照添加到其中的项目顺序进行。这是FIFO 队列的定义。来自MSDN docs

    队列对于按接收顺序存储消息很有用 用于顺序处理。存储在队列中的对象被插入 在一端并从另一端移除。

    【讨论】:

      猜你喜欢
      • 2013-05-29
      • 2015-09-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-16
      • 1970-01-01
      • 2010-11-05
      相关资源
      最近更新 更多