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
相关产品推荐
相关产品推荐

