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

面向对象可变列数容器类设计方案咨询

可变列数数据容器的面向对象设计方案

你需要的是一个能容纳每行列数可变的数据容器,无需为每种列数组合预定义子类。下面是几种无需预定义所有列数组合的可行方案:

方案1:使用键值对字典存储每行数据

直接用Dictionary<string, object>存储每行的列名和对应值,容器类持有这类字典的列表。这种方式完全灵活,不需要预定义任何子类。

public class DynamicColumnContainer
{
    public List<Dictionary<string, object>> Rows { get; } = new List<Dictionary<string, object>>();

    // 辅助方法:添加一行数据
    public void AddRow(Dictionary<string, object> row)
    {
        Rows.Add(row);
    }

    // 示例:添加指定列的行
    public void AddRow(string column1, object value1, string column2, object value2)
    {
        var row = new Dictionary<string, object>
        {
            { column1, value1 },
            { column2, value2 }
        };
        Rows.Add(row);
    }
}

优点:完全灵活,支持任意列数和列名;无需预定义类型。
缺点:丢失编译时类型安全,使用时需要强制转换值类型;没有IntelliSense提示。

方案2:使用强类型的列表存储每行数据

如果每行的数据类型统一(比如都是int),可以用List<T>存储每行的列值,容器类持有List<List<T>>。如果类型不统一,用List<object>。

public class TypedDynamicContainer<T>
{
    public List<List<T>> Rows { get; } = new List<List<T>>();

    public void AddRow(params T[] values)
    {
        Rows.Add(values.ToList());
    }
}

// 使用示例
var container = new TypedDynamicContainer<int>();
container.AddRow(1, 2); // 2列的行
container.AddRow(3, 4, 5, 6); // 4列的行

优点:保持了类型安全;实现简单,无需额外类。
缺点:每行没有列名,只能通过索引访问;如果需要混合类型,只能用object,同样会丢失类型安全。

方案3:使用自定义动态行类

创建一个封装了列值存储的类,通过索引器或泛型方法访问,兼顾灵活性和一定的类型安全。

public class DynamicRow
{
    private readonly List<object> _values = new List<object>();
    public IReadOnlyList<object> Values => _values.AsReadOnly();
    public int ColumnCount => _values.Count;

    public DynamicRow(params object[] values)
    {
        _values.AddRange(values);
    }

    // 索引器访问
    public object this[int index]
    {
        get => _values[index];
        set => _values[index] = value;
    }

    // 泛型方法获取值,避免强制转换
    public T GetValue<T>(int index)
    {
        return (T)_values[index];
    }
}

public class DynamicContainer
{
    public List<DynamicRow> Rows { get; } = new List<DynamicRow>();

    public void AddRow(DynamicRow row)
    {
        Rows.Add(row);
    }

    public void AddRow(params object[] values)
    {
        Rows.Add(new DynamicRow(values));
    }
}

优点:有统一的行类型,容器管理更清晰;通过泛型方法GetValue<T>减少强制转换的繁琐。
缺点:仍然没有列名,只能通过索引访问;类型安全依赖运行时检查。

方案4:结合ExpandoObject实现动态属性行

利用C#的ExpandoObject,可以像访问静态属性一样访问动态添加的列,同时保留灵活性。

public class ExpandoContainer
{
    public List<dynamic> Rows { get; } = new List<dynamic>();

    public void AddRow(dynamic row)
    {
        Rows.Add(row);
    }

    // 示例:创建带指定属性的行
    public dynamic CreateRow(params (string Name, object Value)[] columns)
    {
        dynamic row = new ExpandoObject();
        var rowDict = (IDictionary<string, object>)row;
        foreach (var (name, value) in columns)
        {
            rowDict[name] = value;
        }
        return row;
    }
}

// 使用示例
var container = new ExpandoContainer();
var row1 = container.CreateRow(("ValueA", 1), ("ValueB", 2));
var row2 = container.CreateRow(("ValueA", 3), ("ValueB", 4), ("ValueC", 5), ("ValueD", 6));
container.AddRow(row1);
container.AddRow(row2);

// 访问行数据
int val = row1.ValueA;

优点:支持动态属性访问,语法接近静态类;完全灵活,支持任意列数和列名。
缺点:丢失编译时类型安全,属性名拼写错误只会在运行时暴露;性能略低于静态类型。

方案选择建议

  • 如果需要完全灵活且不介意类型安全:选方案1或方案4。
  • 如果需要类型安全且不需要列名:选方案2。
  • 如果需要统一行类型且希望简化值访问:选方案3。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 02:51:29