C# 队列Queue使用方法 C#如何使用队列数据结构

来源:这里教程网 时间:2026-02-21 17:42:36 作者:

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>

相关推荐