「System.Object 是所有類型的根類別」——這句話幾乎成了 .NET 開發者的共識。但介面 是否也繼承自 Object? 這個看似簡單的問題,觸及類型系統的核心設計哲學。本文從 OO 原則、IL 元數據、編譯器行為三個維度給出確切答案:介面不繼承自 Object。
兩個直觀但錯誤的推論:
.class interface abstract,誤以為是類別因此必繼承 Object。IObjectable obj = new MyObject(); obj.ToString(); 能編譯通過,誤認為介面擁有 Object 成員。介面封裝「行為契約」(如 ICloneable 代表可複製、IEnumerable 代表可枚舉)。若所有介面強制繼承 GetType()、Equals()、GetHashCode()、ToString(),將嚴重污染契約純粹性——ICloneable 實作類別不應被迫承擔 Object 的通用服務契約。.NET 設計者堅持介面不繼承任何基類,保持契約單一、正交。
使用 ILDASM/Reflector 查看任何介面(如 ICloneable、自訂 IObjectable):
.class public interface abstract auto ansi ICloneable
{
.method public hidebysig newslot abstract virtual instance object Clone() cil managed
}
完全沒有 extends [mscorlib]System.Object 標記。 這是元數據層面的鐵證。
ILASM 提供 /noautoinherit 選項,可編譯出不繼承 Object 的類別:
ilasm /exe /output:noobject.exe /noautoinherit my.il
生成的類別如「無根之木」,打破「一切類型繼承 Object」的絕對論述(雖極少實際使用)。
當介面變數呼叫 ToString() 時:
MyObject) 繼承自 Object 的方法。IObjectable.Equals(null, null) 靜態呼叫重寫為 Object.Equals(null, null)。介面方法調用機制(虛介面分派)與一般虛方法分派不同,這也是為何介面不需繼承 Object 即可「使用」其成員的原因。
| 觀點 | 結論 |
|---|---|
| 介面本質是特殊類別 | 特殊就特殊到底:不繼承基類、支援多實作、成員全抽象 |
| 介面變數能呼叫 Object 方法 | 實為實作類別繼承 Object,或編譯器重寫靜態呼叫,非介面自身繼承 |
介面不繼承自 System.Object,這是 .NET 類型系統為保持契約純粹性做出的精妙設計決策。理解這一點,有助於更深層次掌握介面程式設計、虛介面分派與泛型約束的本質。