sealed 是 C# 中一個兼具「架構約束」與「效能優化」雙重意義的關鍵字。它可防止類別被繼承、防止虛擬方法被進一步覆寫,同時讓 JIT 編譯器將虛擬呼叫轉為非虛擬呼叫,減少間接跳轉開銷。本文從語法規則、設計意圖、執行機制三個維度,系統闡述 sealed 的正確用法與進階應用。
public sealed class SealedClass : BaseClass
{
// 實作內容
}
class Derived : SealedClass 皆會導致編譯錯誤 CS0509。sealed abstract 語法非法,因為 abstract 意圖被繼承,sealed 意圖禁止繼承,邏輯衝突。public abstract class EncryptionAlgorithm
{
public abstract byte[] Encrypt(byte[] data, byte[] key);
}
public sealed class Aes256Encryption : EncryptionAlgorithm
{
public override byte[] Encrypt(byte[] data, byte[] key)
{
// 具體 AES 實作,禁止第三方擴展修改演算法核心
using (var aes = Aes.Create())
{
aes.Key = key;
aes.Mode = CipherMode.CBC;
// ...
}
}
}
密封具體實作類別,確保加密邏輯不被竄改,符合安全合規需求。
public class Base
{
public virtual void VirtualMethod() { }
}
public class Middle : Base
{
// 必須同時標記 override 與 sealed
public sealed override void VirtualMethod()
{
// 最終實作,禁止進一步覆寫
}
}
public class Derived : Middle
{
// 編譯錯誤 CS0239:無法覆寫 sealed 方法
public override void VirtualMethod() { }
}
核心規則:只有「覆寫基類虛擬方法」時才能加 sealed;非虛擬方法、介面實作方法不可直接加 sealed。
public abstract class ReportGenerator
{
// 模板方法:定義骨架,禁止子類修改流程
public sealed void GenerateReport()
{
LoadData();
ProcessData();
Render();
Export();
}
protected abstract void LoadData();
protected abstract void ProcessData();
protected virtual void Render() { /* 預設渲染 */ }
protected virtual void Export() { /* 預設匯出 */ }
}
public class PdfReport : ReportGenerator
{
protected override void LoadData() { /* ... */ }
protected override void ProcessData() { /* ... */ }
// 可選擇性覆寫 Render/Export,但無法改變 GenerateReport 流程
}
sealed 保護演算法骨架不被破壞,同時保留局部擴展彈性。
一般虛擬方法調用需經過:
此過程涉及記憶體間接存取,難以內聯,影響 CPU 分支預測與指令管線。
當類別被標記 sealed,或方法被標記 sealed override,JIT 編譯器確知:
因此可將虛擬呼叫 去虛擬化,直接發出 call 指令而非 callvirt,並進一步內聯方法體,實現零開銷抽象。
[Benchmark]
public void VirtualCall() => base.VirtualMethod();
[Benchmark]
public void SealedCall() => sealedInstance.SealedMethod();
// 結果通常顯示 SealedCall 快 10%-30%,並允許內聯
雖然單次呼叫差異微小,但在高頻熱路徑(遊戲迴圈、即時運算、序列化)累積效果顯著。
struct 隱含 sealed,不可被繼承,但可實作介面。sealed(需同時 override 基類虛擬方法或顯式實作)。static class 隱含 abstract sealed,不可實例化、不可繼承、只能含靜態成員。| 場景 | 建議 | 理由 |
|---|---|---|
| 工具類、Helper 類 | ✅ 標記 sealed | 無繼承需求,啟用優化 |
| 演算法具體實作類 | ✅ 標記 sealed | 保護核心邏輯、安全合規 |
| 基礎架構抽象基類 | ❌ 不加 sealed | 預期被繼承擴展 |
| 模板方法公開進入點 | ✅ 標記 sealed | 鎖定流程骨架 |
| 高頻呼叫的虛擬方法 | ✅ 於葉節點類別 sealed override | 消除虛擬呼叫開銷 |
| DPO/實體類別 | ⚠️ 視 ORM 而定 | EF Core 需 proxy 時不可 sealed |
sealed 不只是「禁止繼承」的防禦性標記,更是一把「效能優化」的手術刀。正確使用時機:
sealed override 讓 JIT 去虛擬化。掌握「類別封頂、方法封底、效能加速」三重意義,即能在架構設計與極致效能間遊刃有餘。