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

如何用C#不可变双向链接对象(Records)实现父子双向引用?

C# Records实现双向父子对象链接的便捷方案

在C#中实现父子对象的双向链接(Parent.Child和Child.Parent互指),不需要依赖反射,有几种更直接且类型安全的方案,可根据是否需要保持record的不可变性来选择:

1. 静态工厂方法(保持不可变性)

如果要严格遵循record的不可变设计(使用init属性),可以通过私有构造函数+静态工厂方法封装双向关联逻辑:

public record Parent
{
    public Child? Child { get; init; }
    public string Name { get; init; }

    // 私有构造函数,避免外部直接实例化
    private Parent(string name, Child? child)
    {
        Name = name;
        Child = child;
    }

    // 静态工厂方法,完成双向绑定
    public static Parent CreateWithChild(string parentName, string childName)
    {
        // 先创建未关联子对象的父实例
        var tempParent = new Parent(parentName, null);
        // 创建子对象并关联父实例
        var child = new Child(childName, tempParent);
        // 利用record的with表达式生成关联后的父实例(init属性仅能在初始化时设置)
        return tempParent with { Child = child };
    }
}

public record Child
{
    public Parent Parent { get; init; }
    public string Name { get; init; }

    public Child(string name, Parent parent)
    {
        Name = name;
        Parent = parent;
    }
}

// 使用示例
var parent = Parent.CreateWithChild("ParentA", "ChildA");
// parent.Child.Parent 会指向parent本身

这种方式完全保留record的不可变性,所有属性通过init初始化,关联逻辑被封装在工厂方法中,外部调用无需关心内部细节。

2. 可变属性(最简实现)

如果可以接受部分属性可变(放弃init改用set),可直接在子对象的构造函数中完成双向绑定:

public record Parent
{
    // 使用set允许后续修改
    public Child? Child { get; set; }
    public string Name { get; init; }
}

public record Child
{
    public Parent Parent { get; init; }
    public string Name { get; init; }

    public Child(string name, Parent parent)
    {
        Name = name;
        Parent = parent;
        // 直接给父对象的Child属性赋值,完成双向关联
        parent.Child = this;
    }
}

// 使用示例
var parent = new Parent { Name = "ParentB" };
var child = new Child("ChildB", parent);
// 此时parent.Child和child.Parent已互指

这是代码量最少的实现,但Parent.Child变为可变属性,若不需要严格的不可变性,这是最便捷的方案。

3. 构建器模式(复杂场景适配)

如果对象有较多属性,或需要创建更复杂的关联结构,可用构建器模式封装关联逻辑:

public class ParentChildBuilder
{
    private string _parentName = string.Empty;
    private string _childName = string.Empty;

    public ParentChildBuilder SetParentName(string name)
    {
        _parentName = name;
        return this;
    }

    public ParentChildBuilder SetChildName(string name)
    {
        _childName = name;
        return this;
    }

    public (Parent LinkedParent, Child LinkedChild) Build()
    {
        var tempParent = new Parent(_parentName, null);
        var child = new Child(_childName, tempParent);
        var linkedParent = tempParent with { Child = child };
        return (linkedParent, child);
    }
}

// 对应的不可变record
public record Parent(string Name, Child? Child);
public record Child(string Name, Parent Parent);

// 使用示例
var (parent, child) = new ParentChildBuilder()
    .SetParentName("ParentC")
    .SetChildName("ChildC")
    .Build();

构建器模式把关联逻辑完全封装,外部仅需设置参数并调用Build,适合需要扩展更多关联逻辑的场景。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 13:17:28