sealed 仅用于禁止继承:sealed 类不可被继承但可实例化,sealed override 用于锁定虚方法的进一步重写;不可与 abstract 共存,不可用于非重写方法,是编译期设计约束而非运行时防护。

sealed 不是用来“增强功能”的修饰符,它只干一件事:**关掉继承通道**。用对了能防误用、提升性能、明确设计意图;用错了会直接编译失败,比如和 abstract 一起出现,或者单独用在非重写的方法上。
sealed 类:禁止继承,但允许实例化
当你确定某个类不该被继承(比如封装了敏感逻辑、依赖内部状态不可变、或只是工具集合),就加 sealed:
public sealed class ApiClient
{
private readonly HttpClient _client = new();
public async Task<string> GetAsync(string url) => await _client.GetStringAsync(url);
}
这样写之后,下面这行代码会立刻报错:class MyClient : ApiClient { } → 编译器抛出 CS0509 “无法从密封类型 ApiClient 派生”。
注意点:
-
sealed类仍可被实例化,也能有构造函数、字段、方法、虚成员(只要没被重写) - 不能和
abstract同时出现——抽象类存在的意义就是被继承,密封类的意义是不被继承,二者矛盾 - 结构(
struct)天然就是sealed的,加这个修饰符是冗余且非法的
sealed override:封住某个虚方法的进一步重写
你希望别人能继承你的类,但某些关键行为必须锁定,不让下游再改——这时 sealed override 就派上用场了。它必须和 override 成对出现,且只能用于已存在 virtual 或 abstract 基础的方法。
public class Processor
{
protected virtual void LogStart() => Console.WriteLine("Starting...");
}
public class SecureProcessor : Processor
{
// 这个 LogStart 行为被固定,子类不能再改
protected sealed override void LogStart() => Console.WriteLine("[SECURE] Starting...");
}
public class AuditProcessor : SecureProcessor
{
// ❌ 编译错误 CS0239:无法重写密封的 LogStart
// protected override void LogStart() => ...
}
常见踩坑:
- 漏写
override:只写sealed void LogStart()→ 编译失败,提示“sealed修饰符仅对重写访问器有效” - 试图密封非虚方法:比如密封一个普通
public void DoWork()→ 编译器不认,因为没东西可“封” - 密封后还想调用基类实现:被密封的方法体内仍可用
base.LogStart()(如果基类有该方法),但子类不能再覆盖它
为什么不用 virtual 就够了?还用 sealed?
不声明 virtual 确实能阻止重写,但它也同时阻止了当前类的继承者做任何扩展——哪怕只是加个日志或装饰。而 sealed override 是一种更精细的控制:你允许继承,只锁住特定一两个关键环节。
典型场景:
- 框架基类中定义通用流程骨架(如
Execute()),但要求子类必须调用某校验逻辑(Validate()),于是你在中间层把Validate密封,防止绕过 - DTO 或数据容器类标记为
sealed,避免序列化/反序列化时因继承引入意外字段或行为 - 性能敏感路径:JIT 对密封类的虚方法调用可能做去虚拟化(devirtualization),跳过虚表查找,实测在高频循环中会有微小但可测的收益
容易被忽略的边界情况
sealed 的作用域非常具体,稍不注意就会误判效果:
- 密封类里的
protected成员依然可被本类访问,但派生类拿不到——不是因为访问修饰符变了,而是根本没派生类 - 密封类可以实现接口,也能被泛型约束使用(如
where T : ICloneable, new()中的new()要求类型可实例化,sealed类完全满足) - 反射不受
sealed影响:你能用Activator.CreateInstance实例化密封类,也能通过反射调用其私有方法——sealed是编译期契约,不是运行时防护
真正需要拦住的是设计意图的误用,而不是运行时的越权操作。把它当成一份写给其他开发者的明确注释:这里不欢迎继承,请另寻他路。


















