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

C#通过泛型实现struct循环引用后DLL加载报错如何解决?

问题原因

C# 中结构体是值类型,CLR 加载类型时必须先完成其所有字段类型的加载,才能进一步计算值类型的内存布局和占用大小:

  • 直接定义struct A { A a; }时编译器会直接报错,因为可以直接识别到递归依赖
  • 泛型封装的场景能通过编译,是因为C#编译器在编译阶段仅对开放泛型做语法合法性校验,不会深入校验泛型实例化后的闭环依赖;但CLR加载程序集、解析类型的时候,会遍历所有依赖:Test1依赖Generic<Test2> -> 加载Generic<Test2>这个闭合泛型必须先加载泛型参数Test2 -> Test2依赖Generic<Test1> -> 加载Generic<Test1>又必须先加载Test1,形成类型加载的死循环,最终抛出ReflectionTypeLoadException。
    测试资源管理器找不到测试的问题和该根因一致:测试工具加载程序集枚举类型时会触发同样的类型加载错误。

修复方案

根据业务场景可以选择以下任意一种方案:

  • 最简便的方案:将Test1或Test2任意一个改成类(class)。引用类型的字段仅存储对象指针,大小固定(32位进程4字节、64位进程8字节),不需要递归加载引用对象的完整布局,直接打破依赖循环。
  • 必须保留两个类型为结构体的场景:
    1. 如果你封装的Generic<T>仅做标记用途、不需要存储T相关数据,可以把字段替换为非泛型的标记类型,直接断开泛型依赖链
    2. 确需保留泛型关联的话,可以将其中一个字段的类型改为object或者接口类型,装箱后的值类型字段大小固定,不会触发递归的类型加载
    3. unsafe 场景下可以将字段改为对应结构体的指针类型,指针大小固定,也可以解决问题

内容的提问来源于stack exchange,提问作者Luka Mandić

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 03:15:07