C#中构造函数与对象构造的区别是什么?
构造函数与“对象构造”的核心区别(针对C#只读属性)
首先明确两个概念的范围差异:
- 构造函数:是类/结构体中用于初始化对象的特殊方法,仅能通过
new关键字触发调用,是对象初始化的“传统代码块”入口。 - 对象构造期间:是指从对象开始被创建到完全初始化完成的整个过程,它包含构造函数内部执行的代码,还包括对象初始化器、记录的with表达式、构造函数链调用等场景。
结合两种属性的行为具体说明:
1. 仅get;的只读自动属性
这种属性的赋值权限被严格限制在构造函数内部,哪怕是看起来属于“创建对象”环节的对象初始化器也不允许赋值:
public class Book { public string Title { get; } // 合法:构造函数内赋值 public Book(string title) { Title = title; } } // 编译报错:无法对只读属性“Title”赋值(构造函数或变量初始值设定项中除外) // var book = new Book { Title = "C# in Depth" };
文档描述的“除构造函数外处处不可变”,这里的范围就是严格的构造函数代码块内部,没有扩展到其他初始化场景。
2. get; init;的初始化属性
这种属性的赋值权限覆盖了整个对象构造期间,除了构造函数内部,还支持对象初始化器、记录的with表达式等场景:
public class Book { public string Title { get; init; } // 合法:构造函数内赋值 public Book(string title) { Title = title; } } // 合法:对象初始化器属于构造期间 var book = new Book { Title = "C# in Depth" }; // 如果是记录类型,with表达式也合法(属于新对象的构造期间) public record BookRecord(string Title); var updatedBook = book with { Title = "Advanced C#" };
文档描述的“仅在对象构造期间可变”,这里的构造期间是更宽泛的对象初始化全流程,只要是在对象未完全创建完成的阶段都能赋值,对象创建完成后(比如赋值给变量后再尝试修改Title)就会报错。
核心总结
构造函数是对象构造期间的一个子集,对象构造期间包含了更多C#提供的便捷初始化语法(对象初始化器、with表达式等)。微软文档的描述正是在区分这两种权限范围:仅get;的属性锁死了构造函数这唯一入口,而get; init;则放开到整个对象初始化的全流程。
内容的提问来源于stack exchange,提问作者Shane Amare
相关产品推荐
相关产品推荐

