經過前幾篇 .NET Framework 源碼研究系列的鋪墊,相信讀者已對框架核心實現有了初步認識:其實並不神秘,許多設計思路與我們日常專案開發殊途同歸。但深入細節,總能發現那些平時難以察覺、卻能顯著提升編碼素養的設計智慧。今天,我們聚焦 .NET 類型系統的基石 —— System.Object。
[Serializable]
[ClassInterface(ClassInterfaceType.AutoDual)]
[ComVisible(true)]
public class Object
Serializable 標記支援序列化;ClassInterface 與 ComVisible 則是為 COM 互操作鋪路。對純託管代碼開發者而言,這些屬性鮮少直接打交道,但它們見證了 .NET 兼容既有生態的決心。
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
public Object() { }
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
~Object() { }
空建構函式,猶如宇宙大爆炸前的奇點——萬物起源,一片虛無。重點在於 ReliabilityContract 屬性,它定義了「受限制執行區域」(Constrained Execution Region, CER)內的可靠性契約:
Consistency.WillNotCorruptState:保證不會損壞狀態。Cer.MayFail / Cer.Success:指示方法在 CER 內可能失敗或必定成功。這意味著 CLR 在執行這些關鍵代碼時,會延遲執行緒中止、應用程式域卸載等「帶外異常」,確保關鍵釋放資源邏輯不被打斷。Object 顯式定義析構函式(Finalizer)雖非最佳實踐(會增加 GC 壓力),卻為非託管資源釋放提供了最後防線。
public virtual string ToString() => GetType().ToString();
[MethodImpl(MethodImplOptions.InternalCall)]
public extern Type GetType();
public virtual bool Equals(object obj) => InternalEquals(this, obj);
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern bool InternalEquals(object objA, object objB);
public virtual int GetHashCode() => InternalGetHashCode(this);
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern int InternalGetHashCode(object obj);
MethodImplOptions.InternalCall 揭示真相:這三大核心方法(ToString、Equals、GetHashCode)在 Object 層面只是「馬甲」,真正邏輯下沉至 CLR 內部(C++ 實現)。這也引發一個哲學疑問:Object 真的是所有類型的根基,還是 CLR 內部另有「真·Object」?
源碼中還藏著三個 private 方法,似乎用於透過反射動態讀寫欄位,且能處理 initonly(readonly)檢查與遠端呼叫參數強制轉換。但它們在 Object 內部從未被呼叫,且因 private 修飾,衍生類也無法存取。這段代碼的存在至今仍是個謎——或許是早期 Remoting 架構的殘留,或許是為極少數運行時內部場景預留。唯有微軟工程師知曉真相。
Object 僅百餘行代碼,卻承載了:
研讀 Object,不僅是了解基類,更是窺見 .NET 運行時「以簡馭繁」的架構哲學。