# Queue
概念：
	`Queue` 是 C# 提供的一个==非泛型队列集合==
	队列的特点是：==先进先出==

英文：
	`FIFO`：First In First Out

简单理解：
	像排队买东西
	先排队的人，先被处理

命名空间：
```csharp
using System.Collections;
```

----
# 通常用法
1. 处理需要“按进入顺序依次处理”的数据
2. 保存等待处理的任务
3. 模拟排队、消息、请求等逻辑
4. 学习队列这种数据结构

实际开发中：
	新代码更推荐使用 `Queue<T>`
	这里的 `Queue` 是非泛型版本

----
# 语法
创建：
```csharp
Queue queue = new Queue();
```

入队：
```csharp
queue.Enqueue(数据);
```

出队：
```csharp
object value = queue.Dequeue();
```

查看队头：
```csharp
object value = queue.Peek();
```

数量：
```csharp
queue.Count
```

----
# 基础案例
```csharp
using System;
using System.Collections;

Queue queue = new Queue();

queue.Enqueue("第一个任务");
queue.Enqueue("第二个任务");
queue.Enqueue("第三个任务");

Console.WriteLine(queue.Dequeue());
Console.WriteLine(queue.Dequeue());
Console.WriteLine(queue.Dequeue());
```

输出：
```text
第一个任务
第二个任务
第三个任务
```

理解：
1. `"第一个任务"` 最先进队列
2. `Dequeue()` 会先取出最早进入队列的元素
3. 这就是先进先出

----
# Enqueue、Dequeue、Peek
`Enqueue`：
	把元素添加到队尾

```csharp
queue.Enqueue("A");
```

`Dequeue`：
	取出并删除队头元素

```csharp
object item = queue.Dequeue();
```

`Peek`：
	查看队头元素，但不删除

```csharp
object item = queue.Peek();
```

案例：
```csharp
Queue queue = new Queue();
queue.Enqueue("A");
queue.Enqueue("B");

Console.WriteLine(queue.Peek());    // A
Console.WriteLine(queue.Count);     // 2

Console.WriteLine(queue.Dequeue()); // A
Console.WriteLine(queue.Count);     // 1
```

----
# 遍历
```csharp
Queue queue = new Queue();

queue.Enqueue("A");
queue.Enqueue("B");
queue.Enqueue("C");

foreach (object item in queue)
{
	Console.WriteLine(item);
}
```

输出顺序一般是：
```text
A
B
C
```

理解：
	遍历 `Queue` 时，通常按入队顺序从队头到队尾遍历

----
# 常用成员
```csharp
Queue queue = new Queue();

queue.Enqueue("A");
queue.Enqueue("B");

Console.WriteLine(queue.Count);
Console.WriteLine(queue.Contains("A"));

object first = queue.Peek();
object value = queue.Dequeue();

queue.Clear();
```

常用方法：
1. `Enqueue(object obj)`：入队
2. `Dequeue()`：出队并删除
3. `Peek()`：查看队头但不删除
4. `Contains(object obj)`：判断是否包含
5. `Clear()`：清空
6. `ToArray()`：转成数组

----
# 空队列不能 Dequeue 或 Peek
错误写法：
```csharp
Queue queue = new Queue();

queue.Dequeue();
```

原因：
	队列里没有元素，不能取队头

更稳的写法：
```csharp
if (queue.Count > 0)
{
	object value = queue.Dequeue();
}
```

`Peek()` 也一样，使用前最好先判断 `Count`。

----
# 取值时要类型转换
```csharp
Queue queue = new Queue();
queue.Enqueue(100);

int num = (int)queue.Dequeue();
```

原因：
	非泛型 `Queue` 中的元素按 `object` 存储
	取出来也是 `object`

值类型入队和出队时，也会涉及装箱拆箱：
```csharp
queue.Enqueue(100);          // 装箱
int num = (int)queue.Dequeue(); // 拆箱
```

----
# 适合场景：任务队列
```csharp
Queue taskQueue = new Queue();

taskQueue.Enqueue("加载配置");
taskQueue.Enqueue("读取存档");
taskQueue.Enqueue("进入场景");

while (taskQueue.Count > 0)
{
	string task = (string)taskQueue.Dequeue();
	Console.WriteLine("处理：" + task);
}
```

理解：
	任务按照加入顺序依次处理
	这种情况适合用队列

----
# Queue 和 Stack 的区别
| 对比点 | Queue | Stack |
|---|---|---|
| 规则 | 先进先出 | 后进先出 |
| 英文 | FIFO | LIFO |
| 添加 | `Enqueue` | `Push` |
| 取出 | `Dequeue` | `Pop` |
| 查看 | `Peek` 查看队头 | `Peek` 查看栈顶 |
| 适合场景 | 排队处理任务 | 撤销、回退 |

一句话：
	排队用 `Queue`
	回退用 `Stack`

----
# 注意
1. `Queue` 在 `System.Collections` 命名空间中
2. `Queue` 是非泛型集合，元素按 `object` 存储
3. 队列的规则是先进先出
4. `Enqueue` 是入队
5. `Dequeue` 是出队并删除队头
6. `Peek` 是查看队头但不删除
7. 空队列调用 `Dequeue()` 或 `Peek()` 会出错
8. 新项目通常优先使用 `Queue<T>`

----
# 一句话记忆
==Queue 是先进先出的集合，先进去的先出来。==

----
# 面试/复习时怎么说
可以这样答：

“Queue 是队列结构，特点是先进先出，也就是 FIFO。  
常用方法有 `Enqueue`、`Dequeue` 和 `Peek`，分别表示入队、出队、查看队头。  
非泛型 Queue 存的是 object，取值时可能需要强制类型转换，新项目中更推荐使用 `Queue<T>`。”

----
引用：
1. Microsoft Learn: [Queue Class](https://learn.microsoft.com/en-us/dotnet/api/system.collections.queue?view=net-9.0)
2. Microsoft Learn: [Queue.Enqueue Method](https://learn.microsoft.com/en-us/dotnet/api/system.collections.queue.enqueue?view=net-9.0)
3. Microsoft Learn: [System.Collections Namespace](https://learn.microsoft.com/en-us/dotnet/api/system.collections?view=net-9.0)

#Queue
#队列
#集合
#进阶
