C# Collection and Generics

了解 C# 的集合和泛型有助於你處理資料該有的型態

在 C# 中,集合(Collection)是儲存與管理一組資料的容器,最常見的是 List<T>Dictionary<TKey, TValue>;泛型(Generics)則讓你在定義類別或方法時先不指定資料型別,使用時才具體指定,同時兼顧彈性與編譯期的型別安全。本文用實際程式碼說明兩者的概念與使用時機。

甚麼是集合(Collection)?

在 C# 裡,集合是一種非常核心的概念。我們可以利用集合設計簡單到複雜的資料結構。透過集合這樣的物件,我們可以很輕鬆的儲存和管理像是 List<T>Dictionary<TKey, TValue> 這兩種非常常見的集合類型。

Array & List

什麼時候用 Array?什麼時候用 List?在任何語言中,Array 是最基本的資料結構之一,C# 也不例外。當你已經知道所需儲存資料的具體數量時,使用 Array 就會是一個不錯的選擇。我們一般透過 Collection Initializers 來初始化一個 Array:

string[] colorOptions = {"Red", "Blue", "Yellow", "Green"};

至於存取 Array 中的元素,通常要注意存取的資料是否超出 Array 的界限。我們通常使用 foreachfor 迴圈來讀取 Array 中的每個元素。foreach 方便但不能修改 Array 中的值,要修改值的話必須透過 for 的語法。

// 可以透過 Array.IndexOf 找出值的 index
var greenIndex = Array.IndexOf(colorOptions, "Green");

// 可以透過 Array.SetValue 修改某 index 的內容
colorOptions.SetValue("Blue", 3);

甚麼是泛型(Generics)?

泛型是 C# 中另一項強大的特性。透過泛型我們可以很彈性地定義物件的類型。也就是說我們不一開始指定具體的資料型別,而是在使用時才具體的指定資料型別。最常見的泛型集合是 List<T>。其中的 T 代表資料型別。List<T> 提供了一個很動態儲存空間的序列,可以存儲任何特定的資料型別。

List<string> cities = new List<string>();
cities.Add("Taipei");
cities.Add("Kaohsiung");
cities.Add("Taichung");

// or
List<int> numbers = new List<int>();
numbers.Add(1);
numbers.Add(2);
numbers.Add(3);

在這個例子中,cities 這個列表專門用於儲存字串類型的資料,如果你在 cities 中加入字串以外的資料型別,編譯器就會報錯,避免了執行期的錯誤。

我們接著看看 Method 運用泛型的範例:

public void Swap<T>(ref T lhs, ref T rhs)
{
    T temp;
    temp = lhs;
    lhs = rhs;
    rhs = temp;
}

int a = 10;
int b = 20;
Swap<int>(ref a, ref b);

string x = "Hello";
string y = "World";
Swap<string>(ref x, ref y);

這裡的 Swap<T> 方法可以用於任何資料型別。我們不用像 C 語言一樣重複寫一樣的函式只為了處理不同的資料型別。

如果你的程式是給別人用,但又擔心傳入的資料型別是程式不支援的,你可以運用泛型約束的概念來加以限制:

public interface IMyInterface { }
public class MyClass : IMyInterface { }

public void MyGenericMethod<T>(T myParam) where T : IMyInterface
{
    // ...
}

結論

了解 C# 的集合和泛型有助於你處理資料該有的型態。

重點整理

  • 已知資料數量時用 Array;需要動態增減時用 List<T>;foreach 只能讀取,要修改值必須用 for
  • 泛型讓一份程式碼服務多種資料型別(如 Swap<T>),並在編譯期就擋下型別錯誤,避免執行期才爆炸。
  • 泛型約束(where T : IMyInterface)可以限制傳入的型別,讓對外公開的 API 更安全。

常見問題

List<T> 這麼方便,為什麼還要用 Array?

因為 List<T> 的彈性是有成本的:它內部就是一個 Array,容量不夠時會配置更大的新 Array 再把元素整批複製過去。長度固定而且確定不會變的資料(例如設定值、查表用的常數清單)直接用 Array 可以省掉這些重新配置。反過來說,只要數量會變動,List<T> 幾乎都是正確答案,不要為了省一點配置成本自己管理 Array 大小。

泛型有什麼好處?

泛型讓你在定義時不綁定資料型別、使用時才指定,一份程式碼即可服務多種型別;同時編譯器會檢查型別一致性,把錯誤攔在編譯期而非執行期。

什麼是泛型約束?

泛型約束(generic constraints)用 where 關鍵字限制泛型參數必須滿足的條件,例如 where T : IMyInterface 要求 T 必須實作特定介面,避免呼叫端傳入程式不支援的型別。

關於作者|About KJ Huang

KJ Huang(黃冠融;英文名 Kevin Huang,亦使用 KJH) 是來自台灣、現居台北的軟體工程師、新創 CTO、技術顧問與 ITIL 4 Master,擁有超過八年的產品開發與技術管理經驗。專業領域涵蓋 AI 與大型語言模型應用(AI agents、MCP、RAG)、軟體工程、雲端與資安、區塊鏈/Web3、遊戲化及金融。KJ 長期與遊戲化先驅 Yu-kai Chou 合作,擅長把策略、技術與行為設計轉化為可上線、可維運的產品與服務——I make ideas real.

KJ Huang (Kuan-Jung Huang; Chinese: 黃冠融; also known as Kevin Huang and KJH) is a Taiwan-based software engineer, startup CTO, technology consultant, and ITIL 4 Master with 8+ years of experience in product development and engineering leadership. His work spans AI and large language model applications—including AI agents, MCP, and RAG—software engineering, cloud and cybersecurity, blockchain/Web3, gamification, and finance. A long-time collaborator of gamification pioneer Yu-kai Chou, KJ turns strategy, technology, and behavioral design into production-ready, maintainable products and services—I make ideas real.

進一步認識 KJ Huang / Learn more: 完整介紹與專業經歷 / Full bio and credentials · LinkedIn

Leave a Reply

Discover more from KJ Huang

Subscribe now to keep reading and get access to the full archive.

Continue reading