ArrayList 實作 IList,是 **非泛型動態陣列** 的經典實現:容量自動成長、支援插入/刪除範圍、可存放任意型別。但因 **裝箱/拆箱** 導致實值型別效能損耗,.NET 2.0+ 強烈建議改用 List<T>。
| 特性 | 陣列 T[] | ArrayList |
|---|---|---|
| 容量 | 固定,宣告時決定 | 動態,預設 0 → 4 → 8 → 16…(倍增) |
| 元素型別 | 單一型別 | 任意型別(全部視為 object) |
| 維度 | 支援多維 | 僅一維 |
| 插入/刪除 | 需手動搬移 | Insert/RemoveAt/RemoveRange 內建 |
| 索引存取 | arr[i] | al[i](同樣 O(1)) |
| 分類 | 方法/屬性 | 說明 |
|---|---|---|
| 容量/計數 | Capacity | 取得/設定內部陣列長度 |
Count | 實際元素數 | |
TrimToSize() | 將 Capacity 縮減至 Count,釋放記憶體 | |
| 新增/插入 | Add(obj) | 末尾附加 |
AddRange(coll) | 批次附加 | |
Insert(index, obj) | 指定位置插入,後續元素後移 | |
InsertRange(index, coll) | 批次插入 | |
| 刪除 | Remove(obj) | 移除第一個相符元素 |
RemoveAt(index) | 移除指定索引 | |
Clear() | 清空所有 | |
| 查詢 | Contains(obj) | 線性搜尋 O(n) |
IndexOf(obj) / LastIndexOf | 取得索引位置 | |
| 排序/反轉 | Sort() / Sort(IComparer) | QuickSort,需元素可比較 |
Reverse() / Reverse(index, count) | 就地反轉 |
var al = new ArrayList();
Console.WriteLine($"初始 Capacity={al.Capacity}"); // 0
al.Add("Hello"); // Capacity=4
al.Add("World");
Console.WriteLine($"Count={al.Count}, Capacity={al.Capacity}"); // 2, 4
al.Insert(1, "C#"); // Hello C# World
Console.WriteLine(string.Join(" ", al));
al.Add("."); // Capacity=4
al.Add("---"); // Capacity=8 (擴容)
Console.WriteLine($"擴容後 Capacity={al.Capacity}"); // 8
al.Remove("."); // Count=4, Capacity=8
al.Remove("?"); // 不存在,Count 不變
al.RemoveAt(3); // 移除索引 3
al.TrimToSize(); // Capacity=3
Console.WriteLine($"TrimToSize 後 Capacity={al.Capacity}");
al.Clear(); // Count=0, Capacity=3 (不歸零)
// 新增 int 123 → 裝箱
al.Add(123); // IL: box int32 → 產生 object 參考
// 讀取並運算 → 拆箱
int sum = (int)al[0] + (int)al[1]; // IL: unbox.any int32
形象比喻:把水果(實值型別)裝進大箱子(object),搬運方便但取用時得拆箱。大量運算時 GC 壓力劇增。
List<T> 完美替代| 操作 | ArrayList | List<int> |
|---|---|---|
| 宣告 | var al = new ArrayList(); | var list = new List<int>(); |
| 新增 | al.Add(1); | list.Add(1); // 無裝箱 |
| 讀取 | int x = (int)al[0]; | int x = list[0]; // 直接取值 |
| 遍歷 | foreach(object o in al) | foreach(int x in list) |
| 排序 | al.Sort(); | list.Sort(); |
// 陣列 → ArrayList
int[] arr = {1,2,3};
var al1 = new ArrayList(arr); // 建構子
var al2 = ArrayList.Adapter(arr); // 包裝視圖,修改同步反映原陣列
// ArrayList → 陣列 (需同型別)
var al = new ArrayList { "A", "B", "C" };
string[] arr2 = (string[])al.ToArray(typeof(string)); // 強型別轉換
var al = new ArrayList();
var rnd = new Random();
while (al.Count < 7)
{
int n = rnd.Next(1, 36);
if (!al.Contains(n)) al.Add(n);
}
al.Sort();
foreach (var n in al) Console.Write($"{n} "); // 輸出 7 個已排序號碼
TrimToSize() 養成習慣釋放記憶體。object 接收**。List<T> 零裝箱、強型別、效能更優,除非維護 .NET 1.x 舊碼,否則**不再使用 ArrayList**。下一單元將介紹 Hashtable:鍵值對 O(1) 查找的經典實現。