C#类主构造函数的两种形式:未收录写法是否合规及差异解析
C#主构造函数两种写法的差异与疑问解答
我在测试C#的类主构造函数(primary constructors)新特性时,发现了两种不同的写法,以下是具体示例及展开后的代码:
官方文档示例写法
原始代码
public class C1(int x) { int X = x; int F() => X + 1; }
SharpLab展开后代码
public class C1 { private int X; public C1(int x) { X = x; base..ctor(); } private int F() { return X + 1; } }
简洁隐式写法
原始代码
public class C2(int X) { int F() => X + 1; }
SharpLab展开后代码
public class C2 { [CompilerGenerated] private int <X>PC__BackingField; public C2(int X) { <X>PC__BackingField = X; base..ctor(); } private int F() { return <X>PC__BackingField + 1; } }
针对这两种写法,以下是相关疑问的解答:
1. 为何第二种写法未被官方文档收录?
官方文档优先推荐显式控制成员定义的写法,原因在于:
- 显式写法更直观,能让开发者清晰掌握类成员的定义逻辑,降低认知成本,尤其适合新手理解主构造函数的作用
- 隐式生成backing field属于语法糖的隐式行为,官方更倾向于展示可自定义、可控制的基础用法,避免开发者过度依赖隐式逻辑而忽略底层实现
2. 该写法是否存在不合理之处?
这种简洁写法并非不合理,而是存在局限性:
- 无法自定义生成字段的访问修饰符(只能是编译器默认的private),也不能给字段添加特性、注释等
- 无法在类的其他自定义构造函数中直接访问这个隐式生成的字段,只能通过主构造函数参数传递值
- 如果类中显式定义了同名的
X成员,会直接触发编译冲突 - 调试时,编译器生成的字段名称
<X>PC__BackingField可读性差,不利于调试排查问题
3. 两种写法之间存在哪些实际差异?
- 成员定义方式:第一种是开发者显式声明私有字段
X并手动赋值;第二种由编译器自动生成带[CompilerGenerated]特性的私有backing field,字段名称为编译器内部命名 - 成员可控性:第一种可自由修改字段的访问修饰符、添加特性、调整字段名称;第二种完全由编译器控制,无自定义空间
- 冲突风险:第一种主构造函数参数
x和字段X名称不同,无冲突风险;第二种若类中存在同名显式成员会直接编译报错 - 调试体验:第一种字段名称直观,调试时易查看和修改;第二种生成的字段名称晦涩,调试体验较差
内容的提问来源于stack exchange,提问作者kofifus
相关产品推荐
相关产品推荐

