partial类必须所有部分都用partial修饰,否则编译失败;partial方法返回类型必须为void且仅可在partial类中声明,未实现时调用会被编译器完全移除。

partial 类必须所有部分都用 partial 修饰,缺一个就编译失败
你写两个文件都想参与同一个类定义,但只要其中一个没加 partial 关键字,C# 编译器就直接报错:error CS0263: Partial declarations of 'XXX' must all be 'partial'。这不是警告,是硬性规则。
常见错误现象:把旧类改成 partial 时,只改了新文件,忘了老文件里原来的 class MyClass 还没加 partial;或者复制粘贴时漏掉了关键字。
- 所有同名、同命名空间、同泛型参数的类声明,只要带
partial,就会被合并;不带的会被视为另一个独立类,冲突报错 - 构造函数、字段、属性、方法……任意成员可以分散在不同
partial文件里,但不能重复定义(比如两个文件都写public string Name { get; set; }) - 如果某部分写了基类或接口(如
partial class A : IDisposable),其他部分不能再写——基类和接口只能在一处声明
partial 方法只能在 partial 类里定义,且必须返回 void
partial 方法本质是“可有可无的钩子”:声明在一部分,实现可选地出现在另一部分。如果没人实现它,编译器会直接删掉调用点,零开销。
但限制很死:一旦用了 partial 声明,就必须满足三个条件,否则编译不过:
- 返回类型必须是
void(不能是int、Task、string等任何类型) - 不能有
virtual、override、new、sealed或abstract修饰符 - 必须和类一样,本身在
partial类内部,外部无法声明
典型用法是代码生成场景:T4 模板或 EF Core 的设计时代码生成器提前写好 partial void OnNameChanged(); 声明,你手动在另一个 partial 文件里实现它,触发自定义逻辑。
partial 类常用于代码生成与 UI 设计器协作,不是为手动拆分逻辑而生
很多人以为 partial 是为了“把大类按功能拆到多个文件”,这是误解。它真正解决的是人写代码 + 工具生成代码共存的问题。
使用场景非常具体:
- WinForms / WPF 设计器:拖控件后,设计器自动生成
InitializeComponent()和控件字段声明,全放在Form1.Designer.cs;你写的事件处理、业务逻辑放Form1.cs—— 两者靠partial合成一个类 - EF Core 的
DbContext和实体类:Scaffold-DbContext 生成的代码标记为partial,方便你后续加验证逻辑、计算属性而不被下次生成覆盖 - Source Generators(.NET 5+):生成器输出的代码必须是
partial,才能和手写部分安全合并
手动把一个业务类硬拆成多个 partial 文件,反而增加理解成本,IDE 导航也变麻烦——除非有明确的生成工具配合,否则没必要。
partial 方法不实现时完全消失,别指望它做运行时存在性判断
有人想用 partial 方法做“插件式扩展”,比如检查某个钩子是否被实现再决定流程分支。这行不通:如果没提供实现,编译器不仅删掉方法体,连调用语句都一并剔除。
例如这段代码:
partial void LogDebug(string msg);
// ……
LogDebug("start"); // 如果 LogDebug 没被实现,这行彻底消失,不会抛空引用也不会进断点所以它不适合做条件逻辑开关。真要运行时判断,得用委托、事件或策略模式。
容易踩的坑:
- 调试时发现某段
partial方法调用“没进去”,第一反应不是断点失效,而是——它根本没被实现,已被编译器静默移除 - 文档或注释里写了“可重写此
partial方法”,但使用者忘了加实现,结果逻辑静默跳过,问题难定位 - 不要给
partial方法加 XML 注释(///),因为声明和实现分离,注释放哪都不完整,IDE 也无法聚合显示
真正关键的约束就两条:必须 void,必须成对出现(声明有、实现可选但一旦有就得匹配签名)。其他都是围绕这个设计目标展开的妥协。


















