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

C#源生成器中父子对象初始化的动态最大计数设置方案

解决方案:动态按需创建Child实例,替代预初始化逻辑

核心问题分析

原来的CsharpTypeBase构造函数会递归预创建最多5个子实例,导致两个明显问题:

  • 不需要多层嵌套时,多余的Child实例会浪费内存
  • 嵌套层数超过5时,output.Child!的强制解引用会触发空引用异常

解决思路是移除预创建逻辑,改为在实际需要处理子类型时才动态创建Child实例,同时支持任意深度的嵌套场景。

重构后的CsharpTypeBase类

首先修改基类,彻底去掉构造函数里的自动创建Child逻辑,新增按需创建的方法:

public class CsharpTypeBase
{
    public CsharpTypeBase()
    {
    }

    public bool IsSimple { get; set; }
    public bool IsArray { get; set; }
    public bool IsIEnumerable { get; set; }

    public CsharpTypeBase? Child { get; private set; }

    // 新增方法:确保Child实例存在,不存在则创建
    public CsharpTypeBase EnsureChild()
    {
        return Child ??= new CsharpTypeBase();
    }

    public string? ValueIfIsSimple
    {
        get => _valueIfIsSimple;
        set
        {
            IsSimple = true;
            _valueIfIsSimple = value;
        }
    }

    public CsharpClassModel ClassModel
    {
        get => _classModel;
        set
        {
            IsSimple = false;
            _classModel = value;
        }
    }

    private string?          _valueIfIsSimple;
    private CsharpClassModel _classModel = new();
}

关键改动说明

  1. 移除构造函数的childCount参数和递归创建Child的逻辑,避免预分配不必要的实例
  2. 将Child的ref属性改为普通可空属性,符合常规使用逻辑(若有特殊性能需求可保留ref,但按需创建逻辑不变)
  3. 添加EnsureChild()方法,通过空合并运算符实现“存在则返回,不存在则创建”的逻辑

重构后的类型解析方法

修改FromTypeSyntax方法,在需要处理子类型时,通过EnsureChild()获取或创建Child实例,不再依赖预创建对象:

public static CsharpTypeBase Convert(TypeSyntax typeSyntax)
{
    var output = new CsharpTypeBase();
    FromTypeSyntax(typeSyntax, output);
    return output;
}

private static void FromTypeSyntax(TypeSyntax typeSyntax, CsharpTypeBase output)
{
    switch (typeSyntax)
    {
        case PredefinedTypeSyntax predefinedTypeSyntax:
            output.ValueIfIsSimple = predefinedTypeSyntax.Keyword.ValueText;
            output.IsIEnumerable = false;
            output.IsArray = false;
            break;

        case IdentifierNameSyntax identifierNameSyntax:
            CsharpClassModel.RecursivelyWalkThroughTheClass(identifierNameSyntax.Identifier.ValueText, output);
            break;

        case ArrayTypeSyntax arrayTypeSyntax:
            output.IsArray = true;
            output.IsIEnumerable = false;
            // 确保Child存在后再递归处理元素类型
            FromTypeSyntax(arrayTypeSyntax.ElementType, output.EnsureChild());
            break;

        case GenericNameSyntax genericNameSyntax:
            var (innerClass, isEnumerable) = FindTheMostInnerType(genericNameSyntax);
            output.IsIEnumerable = isEnumerable;
            // 确保Child存在后再递归处理内部类型
            FromTypeSyntax(innerClass, output.EnsureChild());
            break;
    }
}

关键改动说明

  1. 将FromTypeSyntax的第二个参数从ref CsharpTypeBase改为CsharpTypeBase,因为现在不需要修改引用本身,只需修改对象属性
  2. 在处理数组和泛型类型时,调用output.EnsureChild()确保Child实例非空,避免空引用异常
  3. 移除原代码中ref output.Child!的强制解引用,消除潜在的运行时错误

适配所有嵌套场景的验证

该方案可完美适配你列出的所有嵌套类型:

  • List<string>[]:外层数组的Child是List,List的Child是string(简单类型)
  • List<string[]> two:外层List的Child是数组,数组的Child是string
  • Task<List<IReadOnlyCollection<FirstDto>>> three:Task的Child是List,List的Child是IReadOnlyCollection,其Child是FirstDto
  • List<List<List<List<List<List<string>>>>>> seven:6层List嵌套,每一层都会按需创建Child,无层数限制

额外优化建议

  • 若需防止无限嵌套导致栈溢出,可在EnsureChild()中添加嵌套深度计数,超过预设最大值时抛出异常或终止递归
  • 可为CsharpTypeBase添加int Depth属性,跟踪当前类型的嵌套深度,方便调试和日志输出

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 05:35:27