You need to enable JavaScript to run this app. C# 拆分大型类共享变量:解决循环栈溢出并支持跨类调用
优惠活动
大模型
产品
解决方案
定价
更多

C# 拆分大型类共享变量:解决循环栈溢出并支持跨类调用

核心问题根源

你现在的设计从根本上搞反了类之间的继承关系,才会触发无限递归的栈溢出:

  • 继承本质是「is-a」的从属关系,你现在写的DataManageColumns : Data,等于强制把列管理类变成数据类的子类,但列管理的功能是操作数据的工具,和数据本身是「has-a」的组合关系。硬把这种工具类套上继承关系,必然会触发循环实例化:创建Data要实例化列管理类,列管理类因为继承了Data,构造时又要创建新的Data实例,链路永远停不下来,直接耗尽栈内存。
  • 操作类里硬依赖Global.CurrentData()的全局状态,进一步把数据和操作的边界搅得混乱,根本没法同时支持多份独立的CSV数据处理。

落地实现方案

用「组合替代继承」的标准设计思路,就能100%实现你想要的data.xxxManager.Method()的链式调用,完全没有循环依赖:

1. 改造Data类的基础结构

删掉之前错误加的会触发递归的internal DataManageColumns DataManageColumns = new DataManageColumns();字段,把核心数据成员的访问权限调整为同程序集可访问,在类内部实例化各个操作类时,把当前Data的引用直接注入进去:

internal class Data
{
    private readonly int _id;
    protected DateTime LastUpdateTime;
    // 核心数据改为internal访问级别,供同程序集下的操作类读写
    internal readonly List<Column> Columns = new List<Column>();
    internal List<string> DataText = new List<string>();
    internal string Headers;
    internal char Separator;

    // 对外暴露各个操作类的只读属性,实现链式调用
    public DataManageColumns ColumnManager { get; }
    public DataManageSeparator SeparatorManager { get; }
    public DataManageHeaders HeaderManager { get; }

    public Data()
    {
        _id = Global.Last();
        LastUpdateTime = DateTime.Now;
        // 实例化操作类时传入当前实例,因为操作类不继承Data,完全不会触发递归
        ColumnManager = new DataManageColumns(this);
        SeparatorManager = new DataManageSeparator(this);
        HeaderManager = new DataManageHeaders(this);
    }

    public Data(List<string> dataText, char separator, bool hasHeaders) : this()
    {
        DataText = dataText;
        SeparatorManager.Separator = separator;
        if (hasHeaders)
        {
            HeaderManager.SetHeaders();
            HeaderManager.ExcludeHeadersFromDataText();
            ColumnManager.CreateColumns();
        }
    }

    public int GetId() => _id;
}

2. 改造所有操作类的逻辑

把原来操作类继承Data的写法删掉,改成在类内部持有注入的Data实例引用,完全不需要继承就能访问核心数据字段:

// 不再继承Data,从根源上消除递归实例化的可能
class DataManageColumns
{
    // 绑定当前操作类关联的Data实例
    private readonly Data _currentData;

    // 构造时注入绑定的Data,无额外的隐式构造调用
    public DataManageColumns(Data currentData)
    {
        _currentData = currentData;
    }

    public void CreateColumns()
    {
        // 直接通过绑定的实例访问数据,不用再读全局的Global状态
        for (int i = 0; i < _currentData.DataText.Count; i++)
        {
            string[] splitLine = _currentData.DataText[i].Split(_currentData.Separator);
            if (i == 0)
            {
                for (int j = 0; j < splitLine.Length; j++)
                {
                    _currentData.Columns.Add(new Column(j, splitLine[j]));
                }
            }
        }
    }

    public List<Column> GetColumns() => _currentData.Columns;

    public void SetColumns(List<Column> newColumns)
    {
        foreach (Column column in newColumns)
            column.SetSerial(column.GetSerial());
    }
}

剩下的DataManageSeparator、DataManageHeaders全部按同样的逻辑改造:去掉对Data的继承,构造函数接收绑定的Data实例,通过注入的引用读写核心字段即可。

最终调用效果

完全满足你最初的使用预期,没有任何循环依赖、没有全局状态串数据的问题:

// 初始化一份CSV数据
var myCsvData = new Data(rawTextLines, separator: ',', hasHeaders: true);
// 直接通过Data实例调用各个操作类的方法
var allColumns = myCsvData.ColumnManager.GetColumns();
// 随时修改分隔符规则
myCsvData.SeparatorManager.Separator = '\t';
// 重新解析表头
myCsvData.HeaderManager.SetHeaders();

之前尝试的方案的避坑说明

  • 嵌套类实现不了的原因:嵌套类虽然可以访问外部类的私有成员,但本质还是和外部类绑定过紧,只是把代码拆分到不同文件,并没有真正做到单一职责,和partial类的问题一致,只是形式上拆分了文件,没有拆分功能边界。
  • 静态类不适用的原因:静态类没有实例状态,如果你要同时处理多份独立的CSV数据,静态类存的规则会直接串到其他数据实例里,根本没法支持并行的多数据场景。
  • 只要坚持让操作类继承数据类,就必然会触发递归构造——这是C#类构造的基本运行逻辑,不是代码写得是否严谨的问题,是类之间的从属关系从设计上就错了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.24 13:06:02