对象初始化器异常行为:为何可修改只读属性关联对象的属性?
代码运行逻辑与对象初始化语法解析
核心误解:你混淆了两种对象初始化语法
你看到的Test = { Name = "hello" }不是给Test属性赋值,而是C#的嵌套成员初始化语法,它的作用是对已存在的Test实例的成员进行赋值,而非创建新的Test对象赋值给属性。
代码运行完整流程
构造执行顺序:
执行new Child()时,会先调用父类Parent的构造函数(子类构造默认隐式调用父类无参构造)。在Parent的构造里,已经创建了一个Test实例,将其Name设为"Default",并赋值给Parent中**只读(get-only)**的Test属性。对象初始化块的实际作用:
构造函数执行完成后,进入对象初始化块{ Test = { Name = "hello" } }。这个语法等价于:var tempChild = new Child(); tempChild.Test.Name = "hello"; Child child = tempChild;它并没有试图给
Test属性重新赋值(如果这么写Test = new Test { Name = "hello" },会因为Test是get-only属性直接编译报错),而是获取Parent构造已经创建好的Test实例,修改它的Name属性值,把原来的"Default"替换成"hello"。
为什么不会报错?
Parent的Test属性是public Test { get; },虽然没有setter,但外部代码可以读取这个属性的实例(因为get是public的)。Test类的Name属性有set方法,所以可以修改它的值。- 这种成员初始化语法只需要目标对象已经存在,且成员可访问、可修改,不需要属性有setter。
对比验证
如果改成试图给Test属性赋值,会直接触发编译错误:
Child child = new Child { // 编译报错:Test属性是只读的,无法赋值 Test = new Test { Name = "hello" } };
内容的提问来源于stack exchange,提问作者Enei4Life
相关产品推荐
相关产品推荐

