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

C#中使用对象初始化器存储层级数据父对象引用可行吗?

关于对象初始化器中引用父对象的问题

首先直接给结论:C# 里没有专门指代外层正在初始化的父对象的关键字,所以你没法在嵌套的对象初始化器里直接写?Scenario?或?Step?这种引用。想要给子对象的parent属性赋值为父对象,必须拆分步骤,先声明父对象,再给子对象赋值。

传统解决方案:先声明父对象再赋值

你需要先创建父对象实例,再逐个添加子对象,此时就能直接引用已声明的父对象了。针对你的代码,修改后的示例如下:

// 1. 先创建Scenario父对象
var newScenario = new Scenario() 
{ 
    scenarioNumber = Scenarios.Count, 
    scenarioDescription = "Example scenario",
    Steps = new BindingList<Step>()
};

// 2. 添加前两个Step,直接引用newScenario作为parent
newScenario.Steps.Add(new Step(){ parent = newScenario, stepNumber = 1, subSteps = new BindingList<Step>() });
newScenario.Steps.Add(new Step(){ parent = newScenario, stepNumber = 2, subSteps = new BindingList<Step>() });

// 3. 处理带subSteps的第三个Step:先创建这个Step,再添加它的子Step
var thirdStep = new Step(){ parent = newScenario, stepNumber = 3, subSteps = new BindingList<Step>() };
thirdStep.subSteps.Add(new Step() { parent = thirdStep, stepNumber = 1, subSteps = new BindingList<Step>() });
thirdStep.subSteps.Add(new Step() { parent = thirdStep, stepNumber = 2, subSteps = new BindingList<Step>() });
newScenario.Steps.Add(thirdStep);

// 4. 最后将Scenario加入集合
Scenarios.Add(newScenario);

这种方式虽然多了几步,但逻辑清晰,是当前C#语法下最直接的实现方式。

更优雅的替代方案:自动关联父对象

如果你不想每次手动设置parent,可以利用BindingList的AddingNew事件,在子对象被添加到集合时自动绑定父对象。这样能让代码回到对象初始化器的简洁风格,同时避免手动赋值的繁琐。

第一步:修改类的构造函数,添加自动关联逻辑

public class Scenario
{
    public int scenarioNumber { get; set; }
    public string scenarioDescription { get; set; }
    public BindingList<Step> Steps { get; set; }

    public Scenario()
    {
        Steps = new BindingList<Step>();
        // 当向Steps添加新Step时,自动设置parent为当前Scenario
        Steps.AddingNew += (sender, e) =>
        {
            if (e.NewObject is Step step)
            {
                step.parent = this;
            }
        };
    }
}

public class Step
{
    public object parent { get; set; }
    public int stepNumber { get; set; }
    public BindingList<Step> subSteps { get; set; }

    public Step()
    {
        subSteps = new BindingList<Step>();
        // 当向subSteps添加新Step时,自动设置parent为当前Step
        subSteps.AddingNew += (sender, e) =>
        {
            if (e.NewObject is Step subStep)
            {
                subStep.parent = this;
            }
        };
    }
}

第二步:简化后的初始化代码

现在你可以像最开始想的那样用嵌套对象初始化器,不用手动设置parent:

Scenarios.Add(new Scenario() 
{ 
    scenarioNumber = Scenarios.Count, 
    scenarioDescription = "Example scenario",
    Steps = new BindingList<Step>()
    {
        new Step(){ stepNumber = 1 },
        new Step(){ stepNumber = 2 },
        new Step(){ 
            stepNumber = 3, 
            subSteps = new BindingList<Step>() 
            {
                new Step(){ stepNumber = 1 },
                new Step(){ stepNumber = 2 }
            }
        }
    }
});

这种方式更符合面向对象的封装思想,把父对象和子对象的关联逻辑封装在类内部,避免外部代码重复设置。


内容的提问来源于stack exchange,提问作者Jay Double

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 03:35:16