首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 更多程式設計知識

深入解析 C# 中陣列、ArrayList 與 List 的核心差異

     編輯:更多程式設計知識

前言:集合類型的演進

在 C# 開發中,選擇正確的集合類型對效能與程式碼品質至關重要。從早期的陣列,到非泛型的 ArrayList,再到泛型 List<T>,每一代都在解決前一代的痛點。本文將深入剖析三者的記憶體模型、型別安全性、效能特徵與適用場景。

一、陣列:固定大小、連續記憶體的基石

陣列是 C# 中最基礎、也是最早出現的集合結構。它在記憶體中佔據一塊連續區塊,這賦予了它極快的索引存取速度(O(1))。

優點

  • 索引極快:透過位移計算直接定位元素。
  • 記憶體緊湊:無額外物件開銷,對值類型特別友好(避免裝箱)。
  • 語法簡潔:arr[0] = "value" 直觀易懂。

代碼示例

string[] names = new string[3];
names[0] = "Alice";
names[1] = "Bob";
names[2] = "Charlie";
// 修改
names[1] = "Bob Updated";

致命缺陷

  1. 長度不可變:宣告時必須指定大小,過長浪費記憶體,過短拋出 IndexOutOfRangeException。
  2. 插入/刪除昂貴:中間插入需搬移後續所有元素,時間複雜度 O(n)。
  3. 無內建輔助方法:缺乏 Add、Remove、Contains 等常用操作。

二、ArrayList:動態擴容的非泛型嘗試

ArrayList 位於 System.Collections 命名空間,內部以陣列為底層存儲,並在容量不足時自動擴容(通常翻倍)。它實作了 IList 介面,提供豐富的增刪改查方法。

代碼示例

ArrayList list = new ArrayList();
list.Add("Hello");      // 新增字串
list.Add(123);          // 新增整數(隱含裝箱)
list[1] = 456;          // 修改
list.RemoveAt(0);       // 移除首項
list.Insert(0, "World");// 插入至開頭

核心問題:型別不安全與效能損耗

  1. 一切皆 Object:所有元素視為 object,編譯器無法阻止你將 int、string、自訂類別混雜存放。
  2. 頻繁裝箱/拆箱:
    • 裝箱:值類型(如 int)轉為 object 參考類型,在堆上配置記憶體並複製值。
    • 拆箱:從 object 取回值類型,需型別檢查並複製回棧。
    這在大量數值運算時會造成嚴重的 GC 壓力與 CPU 開銷。
  3. 執行時才發現型別錯誤:(int)list[0] 若實際是字串,會拋出 InvalidCastException。

什麼是裝箱與拆箱?

// 裝箱:int → object
int val = 123;
object obj = val; // 隱含裝箱

// 拆箱:object → int
object obj2 = 456;
int val2 = (int)obj2; // 顯式拆箱,需型別檢查

兩者皆涉及記憶體配置與複製,效能成本遠高於直接操作值類型。

三、List<T>:泛型帶來的型別安全與效能飛躍

C# 2.0 引入泛型後,List<T> 成為 ArrayList 的泛型等效類。它同樣實作 IList<T>,API 幾乎一致,但關鍵差異在於編譯期強制型別。

代碼示例

List<int> numbers = new List<int>();
numbers.Add(100);       // 僅接受 int
numbers.Add(200);
// numbers.Add("abc");  // 編譯錯誤:無法將 string 轉換為 int

numbers[0] = 300;       // 直接存取,無拆箱
int first = numbers[0]; // 直接賦值,無裝箱

核心優勢

  • 型別安全:編譯期攔截型別不匹配,杜絕執行時 InvalidCastException。
  • 零裝箱/拆箱:值類型直接存儲在內部陣列中,記憶體佈局緊湊,存取速度接近原生陣列。
  • 程式碼可讀性高:List<Customer> 明確表達集合語意,IDE 智慧提示完整。

四、效能對比總結表

特性 Array (T[]) ArrayList List<T>
記憶體佈局 連續 連續 (Object[]) 連續 (T[])
長度可變 否 是 是
型別安全 是 (編譯期) 否 (執行期) 是 (編譯期)
值類型裝箱 無 頻繁 無
索引存取速度 最快 較慢 (需轉型) 極快 (近似陣列)
適用場景 固定大小、高效能數值運算 舊版相容、極少數動態型別場景 現代 C# 首選

五、最佳實踐建議

  1. 預設選 List<T>:除非有極特殊理由(如互操作、固定大小緩衝區),否則優先使用泛型清單。
  2. 已知固定大小用陣列:如圖像處理像素緩衝、矩陣運算、高頻交易結構體陣列。
  3. 避免 ArrayList:僅維護 .NET Framework 1.x 遺留專案時接觸;新專案嚴禁引入。
  4. 預估容量:new List<int>(10000) 可減少擴容次數,提升大量資料載入效能。
  5. 唯讀場景用 IReadOnlyList<T>:對外暴露介面而非具體類別,防止誤修改。

結語

從陣列到 ArrayList 再到 List<T>,C# 集合演進的核心線索是在保持動態擴容便利性的同時,消除型別不安全與效能損耗。理解底層記憶體模型(連續陣列 vs 物件參考)、裝箱拆箱機制,能幫助你在架構設計與效能調優時做出精準決策。現代 C# 開發中,List<T> 應是 90% 以上集合場景的標準答案。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved