【问题标题】:How does a queue interact with a foreach loop队列如何与 foreach 循环交互
【发布时间】:2015-12-21 18:51:09
【问题描述】:

我真的很惊讶这个问题并没有真正的答案。 例如,我有一个 foreach 循环遍历队列(我使用的是 .Net 版本)foreach 中的队列到底发生了什么? 它是否像标准枚举器一样简单地迭代?或者它是否使用Dequeue() 功能。

为了清楚起见:

Queue<int> q = new Queue<int>();
foreach(int i in q)
{
    // what happens in this loop?
}

【问题讨论】:

  • The documentation for Queue.GetEnumerator() 声明“枚举器可用于读取集合中的数据,但不能用于修改基础集合。” (这适用于大多数类,但不是全部!它肯定适用于队列。)
  • 只需查看MSDN reference of Queue,您就会发现它实现了IEnumerable,因此它可以在foreach(使用枚举器)中使用
  • @MatthewWatson 你的评论听起来像是对我的回答
  • @MatthewWatson 但是为什么它像数组一样使用枚举器呢?为什么不单独实施?

标签: c# foreach


【解决方案1】:

它是否像标准枚举器一样简单地迭代?或者它使用 出队()

它不是迭代队列,而是使用Queue&lt;T&gt;.GetElement 方法在其内部数组中按索引和桶查找元素。你可以在implementation of the Enumerator class returned by Queue&lt;T&gt;.GetEnumerator()看到这个:

public bool MoveNext() 
{
    if (_version != _q._version)
        ThrowHelper.ThrowInvalidOperationException(
                                    ExceptionResource.InvalidOperation_EnumFailedVersion);

    if (_index == -2)
        return false;

    _index++;

    if (_index == _q._size) 
    {
        _index = -2;
        _currentElement = default(T);
        return false;
    }

    _currentElement = _q.GetElement(_index);
    return true;
}

GetElement 就是这样:

internal T GetElement(int i)
{
    return _array[(_head + i) % _array.Length];
}

【讨论】:

  • 为什么它是一个队列时使用标准的Array实现?
  • 因为这就是 Queue 在内部实现的方式。仔细想想,Queue 只是一种抽象数据类型,它公开了 FIFO 实现。一个数组就足以实现那个实现,你只需要知道你的头和尾是什么
  • 这比 MSDN 文档解释的要多得多,谢谢。
【解决方案2】:

根据documentation

枚举器可用于读取集合中的数据,但不能用于修改底层集合。

因此可以安全地假设在队列上使用 foreach 不会使任何项目出队。

【讨论】:

    猜你喜欢
    • 2019-05-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-30
    相关资源
    最近更新 更多