C# 密封类sealed使用方法 C#为什么要将类标记为sealed

来源:这里教程网 时间:2026-02-21 17:39:24 作者:

什么时候必须用
sealed
?不是“可选”,而是设计刚需

当你写的类承载了不可妥协的核心逻辑(比如资金扣减、密钥派生、权限校验),就必须用

sealed
。这不是防御性编码,是架构边界——它让编译器在编译期就堵死所有继承路径,避免子类通过
override
悄悄绕过安全检查。

支付类
Payment
若未密封,别人继承后重写
Pay()
方法,可能把
amount * 0.99
当成扣款逻辑
日志类
SecureLogger
若允许继承,子类可能覆盖
Log()
并跳过敏感字段脱敏
.NET 内置的
string
DateTime
都是
sealed
,因为它们的语义和行为必须绝对稳定

sealed
类为什么能提升性能?JIT 真的会优化它

编译器知道

sealed
类永远不会被继承,所以对它的虚方法调用(哪怕声明为
virtual
)可以跳过虚表查找,直接生成内联或直接调用指令。实测在高频循环中,
sealed
类的方法调用比普通类快约 8%–12%(基于 .NET 6+ JIT 数据)。

这个优化只对实例方法生效;静态方法不受影响 如果类里有大量
virtual
成员但又不打算被继承,不加
sealed
就等于主动放弃 JIT 优化机会
工具类如
MathHelper
sealed
不仅是语义清晰,更是白送的性能红利

常见错误:误以为
sealed
可以和
abstract
共存

这是编译器会立刻报错的组合:

public abstract sealed class X
—— 直接拒绝编译。因为
abstract
要求必须被继承实现,而
sealed
明确禁止继承,二者逻辑互斥。

错误现象:
'X' cannot be both abstract and sealed
真实需求场景:你想限制继承但又需要提供抽象契约?→ 改用接口(
interface
)+ 密封实现类
结构体(
struct
)天然隐式
sealed
,无需、也不能显式加该关键字

密封方法(
sealed override
)比密封类更细粒度的控制

当你的类本身需要被继承(比如框架基类),但其中某个关键方法绝不能被下游再改写,就用

sealed override
。它像给继承链中的某一个齿轮上了锁。

必须同时满足:父类方法是
virtual
→ 子类用
override
重写 → 再加
sealed
阻止进一步重写
示例:
public sealed override void Validate() { ... }
,那么
class Child : Parent
就无法再
override Validate
注意:单独写
sealed void Validate()
(没
override
)是语法错误

真正容易被忽略的点是:密封不是“防黑手段”,而是“防误用手段”。很多团队加

sealed
是为了防止新人在不了解上下文时盲目继承,结果破坏了不可变性或线程安全契约。一旦决定密封,就要同步清理掉所有
virtual
成员——否则留着虚方法却禁止继承,反而造成语义混乱。

相关推荐