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

C# 如何将泛型类型参数作为带实参的泛型使用实现多维存储

报错根本原因

C#泛型系统目前不支持高阶类型参数(Higher-Kinded Types),你定义的TWrapper是封闭的泛型类型参数,仅代表某一个已经构造完成的具体泛型类型,并非可以接收类型参数的开放泛型模板,所以TWrapper<TInner>的写法是非法的,编译器无法识别TWrapper是可填充类型参数的泛型定义。

针对你N维存储的具体场景,有两种可落地的实现方案:

方案1:运行时动态构造类型(兼容现有递归逻辑)

你原本的实现是运行时传入维度参数,本身就不需要编译时确定所有层级的类型,因此可以通过反射动态构造泛型类型,完全实现你要的任意存储类型扩展需求:

public class NDStorage<TInner>
{
    private readonly Type _wrapperOpenType;

    // 构造时传入开放泛型定义,例如typeof(ImmutableArray<>)、typeof(List<>)
    public NDStorage(Type wrapperOpenType)
    {
        // 入参校验,确保传入的是符合要求的开放泛型
        if (!wrapperOpenType.IsGenericTypeDefinition 
            || wrapperOpenType.GetGenericArguments().Length != 1)
        {
            throw new ArgumentException("必须传入仅包含1个类型参数的开放泛型定义", nameof(wrapperOpenType));
        }
        // 额外校验该泛型实现了IList<>,保证支持索引访问
        var testType = wrapperOpenType.MakeGenericType(typeof(object));
        bool implementsIList = testType.GetInterfaces()
            .Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IList<>));
        if (!implementsIList)
        {
            throw new ArgumentException("传入的泛型类型必须实现IList<>接口以支持索引访问", nameof(wrapperOpenType));
        }
        _wrapperOpenType = wrapperOpenType;
    }

    public void MyCallFunction(int dim)
    {
        MyInnerFunction(typeof(TInner), dim);
    }

    private void MyInnerFunction(Type currentLooperType, int dim)
    {
        Console.WriteLine(currentLooperType);
        if (dim < 1) return;
        // 动态构造下一层包装类型
        Type nextWrapperType = _wrapperOpenType.MakeGenericType(currentLooperType);
        MyInnerFunction(nextWrapperType, dim - 1);
    }
}

调用方式如下:

// 用ImmutableArray作为存储结构
var intStorageWithImmutableArray = new NDStorage<int>(typeof(ImmutableArray<>));
intStorageWithImmutableArray.MyCallFunction(4);

// 用List作为存储结构
var intStorageWithList = new NDStorage<int>(typeof(List<>));
intStorageWithList.MyCallFunction(4);

运行后输出和你之前固定ImmutableArray<>的效果完全一致,且支持任意符合要求的泛型存储类型。

方案2:编译时类型安全实现(无需反射,维度固定)

如果你需要完全规避反射、保证编译时类型安全,可以放弃运行时指定维度的能力,改成编译时通过泛型嵌套指定维度,这种方案的实现逻辑如下:

// 定义包装器构造接口
public interface IWrapperFactory
{
    IList<T> Create<T>(IEnumerable<T> items);
}

// 实现ImmutableArray的工厂
public class ImmutableArrayFactory : IWrapperFactory
{
    public IList<T> Create<T>(IEnumerable<T> items) => items.ToImmutableArray();
}

// 实现List的工厂
public class ListFactory : IWrapperFactory
{
    public IList<T> Create<T>(IEnumerable<T> items) => items.ToList();
}

// 固定维度的N维存储,维度通过泛型嵌套实现
public class NDStorage<T, TWrapperFactory> where TWrapperFactory : IWrapperFactory, new()
{
    private static readonly TWrapperFactory Factory = new TWrapperFactory();
    // 对应1维存储的实现,多维度可以通过嵌套NDStorage实现
    public IList<T> Data { get; }

    public NDStorage(IEnumerable<T> data)
    {
        Data = Factory.Create(data);
    }
}

调用时编译时指定维度:

// 2维List<int>存储
var 2dListStorage = new NDStorage<NDStorage<int, ListFactory>, ListFactory>(...);

这种方案适合维度固定的场景,全程编译时类型安全,没有运行时开销。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 06:36:04