You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何保持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 };
    }
}

方案说明

  1. 完全满足所有约束:
    • Wheel的构造函数仍为internal,外部无法直接实例化;
    • 未将init-only属性替换为构造函数参数;
    • Bicycle的公共API结构完全保留,原有用法代码可正常编译运行。
  2. 保持不可变性:Wheel实例一旦创建就无法修改,Bicycle的readonly字段确保内部的Wheel实例只能在初始化阶段替换,实例化后无法变更。

内容的提问来源于stack exchange,提问作者Theodor Zoulias

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 19:47:35