將 ArrayList 遷移至 List<T> 時,會發現部分成員無直接對應。本文詳細說明如何透過介面轉型、擴充方法、替代方案補足功能缺口,並分析預設容量差異對效能的影響。
| ArrayList 成員 | List<T> 對應 | 補償方案 |
|---|---|---|
| IsReadOnly | 無 | ((IList)list).IsReadOnly |
| IsFixedSize | 無 | ((IList)list).IsFixedSize(永遠回傳 false) |
| IsSynchronized | 無 | ((IList)list).IsSynchronized(永遠回傳 false) |
| SyncRoot | 無 | ((IList)list).SyncRoot(回傳 this) |
| Repeat 靜態方法 | 無 | 自訂泛型擴充方法 |
| Clone | 無 | list.GetRange(0, list.Count) |
| Synchronized 靜態方法 | 無 | lock(list) { ... } 或專用同步物件 |
| FixedSize/ReadOnly 靜態方法 | 無 | list.AsReadOnly() 僅支援唯讀 |
List<int> numbers = new List<int>();
// 透過 IList 介面取得非泛型集合相容屬性
Console.WriteLine(((IList)numbers).IsReadOnly); // false
Console.WriteLine(((IList)numbers).IsFixedSize); // false
Console.WriteLine(((IList)numbers).IsSynchronized); // false
Console.WriteLine(((IList)numbers).SyncRoot); // 回傳 numbers 本身
注意:IsFixedSize 與 IsSynchronized 永遠回傳 false,因泛型集合不支援固定大小與內建同步包裝。SyncRoot 回傳 this,建議直接用 lock(numbers)。
public static void Repeat<T>(List<T> list, T obj, int count)
{
if (count < 0)
throw new ArgumentException("count 必須 >= 0");
for (int i = 0; i < count; i++)
list.Add(obj);
}
// 使用範例
var list = new List<string>();
Repeat(list, "Hello", 3); // 加入 3 個 "Hello"
List<int> oldList = new List<int> { 1, 2, 3, 4, 5 };
// 複製全部元素
List<int> newList = oldList.GetRange(0, oldList.Count);
// 驗證獨立性
newList[0] = 99;
Console.WriteLine(oldList[0]); // 1(原始未變)
Console.WriteLine(newList[0]); // 99
GetRange 執行淺拷貝,參考型別元素仍指向同一物件,行為接近 ArrayList.Clone()。
// 非泛型寫法(已淘汰)
var syncList = ArrayList.Synchronized(list);
// 泛型標準寫法
private readonly object _lock = new object();
lock (_lock) { list.Add(item); }
// 或直接鎖定列表本身(簡單場景)
lock (list) { list.Add(item); }
微軟移除內建同步包裝,因其提供錯誤的安全感(複合操作仍需外部鎖定)。顯式 lock 更清晰、可控。
| 集合類型 | 預設初始容量 | 擴容次數(加入 17 元素) |
|---|---|---|
| ArrayList | 16 | 1 次(16→32) |
| List<T> | 4 | 3 次(4→8→16→32) |
建議:若預估元素數量,建構時指定容量 new List<T>(estimatedCount) 避免多次擴容重新分配記憶體。
ConvertAll<TOutput>(Converter<T, TOutput>) - 型別轉換投影Find/Predicate<T>、FindAll、FindIndex、FindLast - 條件搜尋ForEach(Action<T>) - 內建迴圈動作Exists/TrueForAll - 量詞邏輯TrimExcess() - 釋放未使用容量遷移 ArrayList 至 List<T> 不僅是型別安全提升,更獲得豐富的函數式操作方法。雖少數非泛型成員需透過 IList 介面或自訂方法補足,但整體 API 設計更現代、更強大。記住指定初始容量以發揮最佳效能。