繼上篇分析 List<T> 後,本文對比 ArrayList (非泛型) 與 LinkedList<T> (泛型) 的源碼實現,揭示兩者在 .NET 架構中的不同定位與設計取捨。
源碼物理路徑揭示核心差異:
ArrayList:redbits\ndp\clr\src\BCL\System\Collections — **CLR 基礎類庫 (BCL) 核心層**LinkedList<T>:redbits\ndp\fx\src\CompMod\System\Collections\Generic — **框架擴展層 (FX/CompMod)**結論:ArrayList 是運行時核心組件,LinkedList 是上層擴展組件。兩者層級不同,缺乏直接可比性。
public class ArrayList : IList, ICloneable
{
private object[] _items;
private int _size;
private int _version;
[NonSerialized] private object _syncRoot;
private const int _defaultCapacity = 4;
private static readonly object[] emptyArray = new object[0];
...
}
object[] 動態陣列,擴容邏輯 (2倍)、_version 迭代器失效機制、Array.Copy 批量操作幾乎一致。ArrayList 存儲 object,涉及**裝箱/拆箱**開銷;List<T> 強型別,避免裝箱。ArrayList 實現 ICloneable (淺複製);List<T> 未實現。淺複製語意在引用型別元素下極易誤用,設計初衷存疑。
public virtual int IndexOf(object value)
{
return Array.IndexOf((Array)_items, value, 0, _size); // value 裝箱
}
[Serializable]
public class LinkedList<T> : ICollection<T>, ICollection, ISerializable, IDeserializationCallback
{
internal LinkedListNode<T> head;
internal int count;
internal int version;
private object _syncRoot;
private SerializationInfo siInfo; // 反序列化暫存
const string VersionName = "Version", CountName = "Count", ValuesName = "Data";
...
}
LinkedListNode<T> 內含 Prev/Next/List/Value,所有操作 (AddFirst/Last/Before/After) 均維護雙向鏈接完整性。Enumerator 同時實現 IEnumerator、ISerializable、IDeserializationCallback,確保枚舉狀態可跨應用程式域流動。IDeserializationCallback.OnDeserialization 在物件圖完全反序列化後,從 SerializationInfo 取出陣列逐項 AddLast 重建鏈結:
public virtual void OnDeserialization(object sender)
{
if (siInfo == null) return;
int realVersion = siInfo.GetInt32(VersionName);
int count = siInfo.GetInt32(CountName);
if (count != 0)
{
T[] array = (T[])siInfo.GetValue(ValuesName, typeof(T[]));
foreach (T item in array) AddLast(item);
}
else head = null;
version = realVersion;
siInfo = null;
}
此模式優於四大序列化回調屬性 (OnDeserializedAttribute 等),因能確保依賴圖中其他物件已就緒。
| 維度 | ArrayList | LinkedList<T> |
|---|---|---|
| 層級 | CLR BCL 核心 | FX 擴展組件 |
| 資料結構 | 動態陣列 | 雙向鏈表 |
| 型別安全 | 無 (object) | 泛型強型別 |
| 隨機存取 | O(1) | O(n) |
| 插入/刪除 | O(n) 位移 | O(1) 節點操作 |
| 序列化支援 | ICloneable (淺複製) | ISerializable + IDeserializationCallback (完整圖重建) |
| 列舉器穩定性 | _version 機制 | _version + 節點引用驗證 |
List<T>:型別安全、無裝箱、效能優於 ArrayList。LinkedList<T>。ISerializable + IDeserializationCallback 模式,在 OnDeserialization 中重建引用關係,比單純屬性回調更可靠。微軟源碼並非神秘黑盒,其實現邏輯與我們自行編寫集合類別時的思路高度一致,差異在於邊界處理、介面契約履行、序列化穩健性等工程細節上的打磨。閱讀源碼,重在學習這些「專業細節」。