应使用泛型 new queue() 初始化队列,避免过时的非泛型 queue;入队用 enqueue(),出队用 dequeue()(空时抛 invalidoperationexception),查看队首用 peek();判空用 count == 0,遍历推荐 foreach 或 while (q.count > 0);多线程场景应选 concurrentqueue 或 blockingcollection;勿将 queue 当 stack 用,其为 fifo 结构。

Queue 初始化和基本操作
直接用 new Queue<t>()</t> 创建泛型队列,这是最安全、最常用的方式。非泛型 Queue 已过时,不推荐在新代码中使用,它会引发装箱/拆箱开销且缺乏类型安全。
入队用 Enqueue(),出队用 Dequeue(),查看队首用 Peek()(不移除)。注意 Dequeue() 在队列为空时抛出 InvalidOperationException,不是返回 null 或默认值。
var q = new Queue<string>();
q.Enqueue("first");
q.Enqueue("second");
Console.WriteLine(q.Peek()); // 输出 "first"
Console.WriteLine(q.Dequeue()); // 输出 "first",队列剩 ["second"]判断是否为空和遍历队列
Count 属性返回当前元素数量,Count == 0 是判断空队列的可靠方式;别用 Peek() + 异常捕获来“试探”,这属于反模式。
遍历时不能边遍历边 Dequeue()(除非你明确要清空),否则会跳过元素或抛异常。需要只读遍历就用 foreach;需要逐个处理并移除,用 while (q.Count > 0) 循环更清晰:
while (q.Count > 0)
{
var item = q.Dequeue();
Process(item);
}线程安全问题:Queue 不是线程安全的
多个线程同时调用 Enqueue() 或 Dequeue() 可能导致数据错乱或异常,.NET 没有内置锁机制。不要自己加 lock 包裹每次操作——性能差且易出错。
正确做法是:
- 短期方案:改用 ConcurrentQueue<t></t>,它提供无锁的 TryEnqueue() 和 TryDequeue(),返回 bool 表示是否成功
- 长期方案:评估是否真需要多线程共享队列,有时用生产者-消费者模式 + BlockingCollection<t></t> 更合适
常见错误:把 Queue 当 Stack 用
有人误以为 Peek() + Dequeue() 能实现后进先出,但 Queue 是 FIFO,最后入队的永远在队尾。如果需要 LIFO 行为,直接换用 Stack<t></t>。
另一个典型错误是反复调用 Peek() 以为能“预读多个元素”——它只返回队首,不会移动内部指针。想看前 N 个?只能复制一份再遍历,或者改用 List<t></t> 并手动维护索引。
队列容量不是硬限制,Queue<t></t> 内部是循环数组,自动扩容;但频繁扩容会影响性能,如果预估大小较稳定,初始化时传入容量参数更高效:new Queue<int>(1024)</int>。








