C# 中,即使類別宣告為 abstract,仍必須實作介面所有成員,不可留待衍生類別實作:
interface IOne {
void A();
}
// 編譯錯誤:'BaseOne' does not implement interface member 'IOne.A()'
abstract class BaseOne : IOne {
// 無法只宣告不實作 A()
}
Java 允許抽象類別部分實作介面,剩餘成員由具體子類別完成:
// Java - 合法
abstract class BaseOne implements IOne {
// 可不實作 A()
}
void IOne.A() { throw new NotImplementedException(); }(編譯通過,執行期失敗)out 參數不支援協變:out Derived 不能轉為 out Base。
void Foo(out Base b) {
b = new Base(); // 合法:將 Base 實例指派給 Base 參考
}
Derived d = null;
Foo(out d); // 若允許:Foo 內部將 Base 指派給 d,導致 d 指向 Base 實例 → 型別安全破壞
d.DerivedOnlyMethod(); // 執行期崩潰!
out T 相當於 T*(指向 T 的指標)in/ref/傳值參數支援協變(唯讀情境安全)// 唯讀參考,支援協變,避免複製大型結構體
void Process(in BigStruct data) { ... }
// 回傳唯讀參考
ref readonly BigStruct GetData() { ... }
C# 在型別系統一致性上採取更嚴格立場:抽象類別必須完整實作介面、out 參數禁用協變。這些限制看似減少靈活性,實則在編譯期攔截整類執行期錯誤,符合 C#「靜態型別安全優先」的設計核心。