泛型版 Queue<T> 與 Stack<T> 不支援非泛型版本擁有的 Clone() 方法(因未實作 ICloneable)。本文介紹利用建構函數接受 IEnumerable<T> 參數的特性,優雅實現佇列與堆疊的淺拷貝。
Queue<T> 與 Stack<T> 皆提供建構函數:
public Queue(IEnumerable<T> collection)
public Stack(IEnumerable<T> collection)
此建構函數會遍歷來源集合,將元素順序加入新實例。因兩者皆實作 IEnumerable<T>,可直接將現有實例傳入建立副本。
public static void CloneQueue()
{
// 建立原始佇列
Queue<int> numericQueue = new Queue<int>();
numericQueue.Enqueue(1);
numericQueue.Enqueue(2);
numericQueue.Enqueue(3);
// 複製:傳入實作 IEnumerable<T> 的原始佇列
Queue<int> clonedNumericQueue = new Queue<int>(numericQueue);
// 驗證:foreach 不移除元素,僅檢視
Console.WriteLine("=== 複製後內容(foreach 檢視)===");
foreach (int i in clonedNumericQueue)
{
Console.WriteLine($"foreach: {i}");
}
// 實際 Dequeue 驗證獨立性
Console.WriteLine("\n=== Dequeue 順序 ===");
Console.WriteLine(clonedNumericQueue.Dequeue()); // 1
Console.WriteLine(clonedNumericQueue.Dequeue()); // 2
Console.WriteLine(clonedNumericQueue.Dequeue()); // 3
}
=== 複製後內容(foreach 檢視)===
foreach: 1
foreach: 2
foreach: 3
=== Dequeue 順序 ===
1
2
3
public static void CloneStack()
{
// 建立原始堆疊
Stack<int> numericStack = new Stack<int>();
numericStack.Push(1);
numericStack.Push(2);
numericStack.Push(3);
// 複製
Stack<int> clonedNumericStack = new Stack<int>(numericStack);
// 驗證
Console.WriteLine("=== 複製後內容(foreach 檢視)===");
foreach (int i in clonedNumericStack)
{
Console.WriteLine($"foreach: {i}");
}
Console.WriteLine("\n=== Pop 順序 ===");
Console.WriteLine(clonedNumericStack.Pop()); // 3 (LIFO)
Console.WriteLine(clonedNumericStack.Pop()); // 2
Console.WriteLine(clonedNumericStack.Pop()); // 1
}
=== 複製後內容(foreach 檢視)===
foreach: 1
foreach: 2
foreach: 3
=== Pop 順序 ===
3
2
1
| 行為 | Queue<T> | Stack<T> |
|---|---|---|
| 複製順序 | 保持 FIFO 順序(先進先出) | 保持 LIFO 邏輯順序(後進先出) |
| foreach 迭代順序 | 1 → 2 → 3(Dequeue 順序) | 1 → 2 → 3(Push 順序,非 Pop 順序) |
| 獨立性 | 副本操作不影響原始實例,反之亦然 | |
| 拷貝深度 | 淺拷貝(參考型別元素共享同一物件實例) | |
.NET 設計團隊決定移除泛型集合的 ICloneable 支援,因為:
ICloneable 未定義淺/深拷貝語意,導致使用者誤解IEnumerable<T> 提供更明確、型別安全的複製方式new List<T>(source)、new HashSet<T>(source) 等同樣模式泛型 Queue<T> 與 Stack<T> 雖無 Clone(),但透過接受 IEnumerable<T> 的建構函數,提供更清晰、型別安全的複製機制。此模式適用於所有實作 IEnumerable<T> 的泛型集合,是 .NET 集合框架的標準複製慣用語。