如何保持init-only特性并将属性值传递给内部Wheel类?
问题描述
我有一个Wheel类,包含两个init-only属性Spokes(辐条数)和DiskBrake(碟刹):
public class Wheel { internal Wheel() { } public int Spokes { get; init; } public bool DiskBrake { get; init; } }
该类要求Wheel实例化后属性必须不可变,因此属性设为init-only类型,由readonly字段支持。
我还有一个Bicycle类,包含两个Wheel实例:
public class Bicycle { private readonly Wheel _frontWheel = new(); private readonly Wheel _rearWheel = new(); public int FrontWheelSpokes { get => _frontWheel.Spokes; init => _frontWheel.Spokes = value; } public int RearWheelSpokes { get => _rearWheel.Spokes; init => _rearWheel.Spokes = value; } public bool FrontWheelDiskBrake { get => _frontWheel.DiskBrake; init => _frontWheel.DiskBrake = value; } public bool RearWheelDiskBrake { get => _rearWheel.DiskBrake; init => _rearWheel.DiskBrake = value; } }
预期用法如下:
Bicycle bicycle = new() { FrontWheelSpokes = 32, RearWheelSpokes = 24, FrontWheelDiskBrake = true, RearWheelDiskBrake = false };
但这段代码无法编译,在init => _xxxWheel.Yyy = value;这几行出现四个编译错误:
Init-only property or indexer 'Wheel.Spokes' can only be assigned in an object initializer, or on 'this' or 'base' in an instance constructor or an 'init' accessor.
请问能否在不破坏Wheel和Bicycle两类所有属性的“init-only特性”的前提下,修复这些编译错误?
约束条件:
- 不暴露
Wheel类构造函数给外部,仅Bicycle自身可实例化车轮。 - 不将init-only属性替换为构造函数参数。
- 不修改
Bicycle的公共API结构。
修复方案
核心思路是:不能直接修改已有Wheel实例的init-only属性,而是通过创建新的Wheel实例(在对象初始化器中设置属性),再将新实例赋值给readonly字段——因为readonly字段允许在init访问器中重新赋值。
修改后的Bicycle类代码如下:
public class Bicycle { private readonly Wheel _frontWheel = new(); private readonly Wheel _rearWheel = new(); public int FrontWheelSpokes { get => _frontWheel.Spokes; init => _frontWheel = new Wheel { Spokes = value, DiskBrake = _frontWheel.DiskBrake }; } public int RearWheelSpokes { get => _rearWheel.Spokes; init => _rearWheel = new Wheel { Spokes = value, DiskBrake = _rearWheel.DiskBrake }; } public bool FrontWheelDiskBrake { get => _frontWheel.DiskBrake; init => _frontWheel = new Wheel { Spokes = _frontWheel.Spokes, DiskBrake = value }; } public bool RearWheelDiskBrake { get => _rearWheel.DiskBrake; init => _rearWheel = new Wheel { Spokes = _rearWheel.Spokes, DiskBrake = value }; } }
方案说明
- 完全满足所有约束:
Wheel的构造函数仍为internal,外部无法直接实例化;- 未将init-only属性替换为构造函数参数;
Bicycle的公共API结构完全保留,原有用法代码可正常编译运行。
- 保持不可变性:
Wheel实例一旦创建就无法修改,Bicycle的readonly字段确保内部的Wheel实例只能在初始化阶段替换,实例化后无法变更。
内容的提问来源于stack exchange,提问作者Theodor Zoulias
相关产品推荐
相关产品推荐

