C# .NET中readonly、private set、init与仅get属性的区别解析
C# 10 属性访问修饰符对比与代码有效性分析
首先明确:你给出的代码不完全有效,问题出在public int Id {get;};——这个自动属性仅定义了getter,但后备字段未被初始化,编译器会抛出错误。必须通过字段初始化器(如public int Id {get;} = 0;)或构造函数赋值才能合法。其余属性语法均符合C# 10规范。
下面逐个分析每个属性的特性,结合你的猜测纠正讲解:
1. public int Id {get;};
你的猜测:必须在设计时硬编码定义,且永远无法修改?
- 语法上不合法,需补充初始化逻辑(字段初始化器或构造函数赋值)。
- 修正后,该属性是只读属性:只能在初始化阶段(字段初始化器、构造函数)赋值,对象创建完成后无法修改。类比Java中
private final int id;搭配public getter,且仅在构造器中初始化的写法。
2. public string Dept {get; set;};
你的猜测:可变——可多次修改?
- 完全正确。这是标准的读写自动属性,外部任意代码都可以读取和修改属性值,无访问限制。类比Java中常规的
private String dept;搭配public getter、setter的写法。
3. public string FirstName {get; readonly set;};
你的猜测:不确定
- 这是C# 9+支持的语法,
readonly set限制setter仅能在类的构造函数或字段初始化器中被调用,外部代码无法修改属性值。 - 初始化完成后属性值不可变更,效果类似只读属性,但允许在构造器中通过setter语法赋值(如
this.FirstName = "Alice";),写法更灵活。类比Java中private final String firstName;,仅允许在构造器中赋值。
4. public string LastName {get; private set;};
你的猜测:不确定
private set表示setter的访问权限为私有,只有当前类内部的代码可以调用setter修改属性值,外部仅能读取。- 和只读属性的区别是:类内部的任意方法(比如业务逻辑方法)可以随时修改该属性值,而只读属性初始化后完全不可变。类比Java中
private String lastName;搭配public getter、private setter的写法。
5. public string DateOfJoining {get; init;};
你的猜测:不可变——仅能在构造函数中设置一次?
- 不完全准确。
init是C# 9引入的初始化 setter,除了构造函数,还允许在对象初始化器中赋值(如new Employee { DateOfJoining = "2024-05-20" }),但对象初始化完成后(构造+初始化器执行完毕),就再也无法修改。 - 这是一种更灵活的不可变属性定义方式,类比Java中record类型的属性,或通过Builder模式初始化后不可变的字段,但C#的
init语法更简洁直接。
内容的提问来源于stack exchange,提问作者Manish Bansal
相关产品推荐
相关产品推荐

