集合(Collections)是程式中用來儲存「多筆資料」的結構,從陣列(array)到 List<T>
、Dictionary<TKey,TValue>
、HashSet<T>
、Queue<T>
、Stack<T>
……各種集合各有特性與適合的應用場景。理解常見集合的行為與使用範例是寫出穩定、可維護後端程式的基礎。
List<T>
:最常使用的動態陣列(可增減且支援索引),適合順序資料與常見操作。Dictionary<TKey,TValue>
:鍵值對映射(key → value),用於快速查找資料。HashSet<T>
:儲存不重複元素、查詢/新增速度快(集合成員唯一)。Queue<T>
/ Stack<T>
:分別代表 FIFO(隊列)與 LIFO(堆疊)行為。int[] nums = new int[3];
nums[0] = 10;
nums[1] = 20;
nums[2] = 30;
Console.WriteLine(nums[1]); // 輸出 20
List<T>
(動態)List<T>
是開發中最常用的通用集合—可動態增減、支援索引與許多便利方法(Add、Remove、Find 等)。
using System;
using System.Collections.Generic;
class Program
{
static void Main()
{
List<int> list = new List<int>();
list.Add(10);
list.Add(20);
list.Add(30);
list.Remove(20);
Console.WriteLine(list[1]); // 輸出 30
}
}
Dictionary<TKey, TValue>
(鍵值對)Dictionary 在需要以 key 快速查詢時非常合用(例如 id → 物件、設定檔鍵值等)。
using System;
using System.Collections.Generic;
var dict = new Dictionary<string, int>();
dict["apple"] = 3;
dict["banana"] = 5;
if (dict.TryGetValue("apple", out int qty))
{
Console.WriteLine($"apple: {qty}"); // apple: 3
}
HashSet<T>
(不重複集合)當你只要「存在性檢查」或想確保集合中的元素不重複時,HashSet<T>
是很好的選擇。
var set = new HashSet<int>();
set.Add(1);
set.Add(1); // 重複元素會被忽略
Console.WriteLine(set.Count); // 1
Queue<T>
/ Stack<T>
// Queue (FIFO)
var q = new Queue<string>();
q.Enqueue("first");
q.Enqueue("second");
Console.WriteLine(q.Dequeue()); // first
// Stack (LIFO)
var s = new Stack<string>();
s.Push("a");
s.Push("b");
Console.WriteLine(s.Pop()); // b
集合提供了一種彈性的方式來處理物件群組,可以依照以下特性來分類不同的集合:
System.Collections.Generic.List<T>
。其他集合則透過鍵 (key) 來存取元素,元素的值會與單一鍵相關聯。最常見的範例是 System.Collections.Generic.Dictionary<TKey,TValue>
。應根據應用程式存取元素的方式,來選擇使用哪一種集合。Array、System.Span<T>
和 System.Memory<T>
不支援動態增減元素。下面的範例建立並初始化一個字串列表,刪除一個元素,並將一個元素加入列表末尾。每次修改後,它使用 foreach 語句或 for 迴圈遍歷字串:
// Create a list of strings by using a
// collection initializer.
List<string> salmons = ["chinook", "coho", "pink", "sockeye"];
// Iterate through the list.
foreach (var salmon in salmons)
{
Console.Write(salmon + " ");
}
// Output: chinook coho pink sockeye
// Remove an element from the list by specifying
// the object.
salmons.Remove("coho");
// Iterate using the index:
for (var index = 0; index < salmons.Count; index++)
{
Console.Write(salmons[index] + " ");
}
// Output: chinook pink sockeye
// Add the removed element
salmons.Add("coho");
// Iterate through the list.
foreach (var salmon in salmons)
{
Console.Write(salmon + " ");
}
// Output: chinook pink sockeye coho
下面的範例按索引從清單中刪除元素,不是使用 foreach 語句,而是使用降序迭代的 for 語句。 RemoveAt 方法使已刪除元素之後的元素具有較低的索引值:
List<int> numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
// Remove odd numbers.
for (var index = numbers.Count - 1; index >= 0; index--)
{
if (numbers[index] % 2 == 1)
{
// Remove the element by specifying
// the zero-based index in the list.
numbers.RemoveAt(index);
}
}
// Iterate through the list.
// A lambda expression is placed in the ForEach method
// of the List(T) object.
numbers.ForEach(
number => Console.Write(number + " "));
// Output: 0 2 4 6 8
對於 List<T>
中元素的型別,也可以定義自己的類別。下面的範例中,程式碼中定義了 List<T>
使用的 Galaxy 類別:
private static void IterateThroughList()
{
var theGalaxies = new List<Galaxy>
{
new (){ Name="Tadpole", MegaLightYears=400},
new (){ Name="Pinwheel", MegaLightYears=25},
new (){ Name="Milky Way", MegaLightYears=0},
new (){ Name="Andromeda", MegaLightYears=3}
};
foreach (Galaxy theGalaxy in theGalaxies)
{
Console.WriteLine(theGalaxy.Name + " " + theGalaxy.MegaLightYears);
}
// Output:
// Tadpole 400
// Pinwheel 25
// Milky Way 0
// Andromeda 3
}
public class Galaxy
{
public string Name { get; set; }
public int MegaLightYears { get; set; }
}