如何通过JIT编译器编译泛型?

Yoc*_*mer 28 c# compiler-construction generics jit

我知道泛型是由JIT编译的(就像其他所有东西一样),与编译代码时生成的模板形成对比.
问题是可以使用反射在运行时创建新的泛型类型.
这当然会影响通用的约束.哪个已经通过了语义解析器.

有人能解释一下这是如何处理的吗?究竟发生了什么?
(代码生成和语义检查)

Ani*_*Ani 37

我建议在C#,Java和C++中阅读Generics:与Anders Hejlsberg的对话.

Qn 1.如何通过JIT编译器编译泛型?

从采访中:

Anders Hejlsberg:[...]在CLR [公共语言运行时]中,当您编译List或任何其他泛型类型时,它会像任何普通类型一样编译为IL [中间语言]和元数据.当然,IL和元数据包含知道有类型参数的附加信息,但原则上,泛型类型只编译任何其他类型编译的方式.在运行时,当您的应用程序首次引用List时,系统会查看是否有人已经要求 List<int>.如果没有,它会向JIT提供IL和元数据List<T> 以及类型参数int.在JITing IL的过程中,JITer也替换了类型参数.

[...]

现在,我们接下来要做的是所有类型实例化都是值类型 - 例如List<int>, List<long>, List<double>, List<float>-we创建可执行本机代码的唯一副本.所以List<int>得到自己的代码. List<long>得到自己的代码. List<float>得到自己的代码.对于所有引用类型,我们共享代码,因为它们在表示上是相同的.这只是指针.


Qn 2.事情是,可以使用反射在运行时创建新的泛型类型.这当然会影响通用的约束.哪个已经通过了语义解析器.有人能解释一下这是如何处理的吗?

从本质上讲,IL保留了泛型类型的高级视图,它允许CLR在运行时检查"动态构造的"泛型类型的约束,就像C#编译器可能对C#源代码中的"静态构造"类型一样.编译时间.

这是另一个片段(强调我的):

Anders Hejlsberg:[...]有了约束,你可以提升代码的动态检查,并在编译时或加载时验证它.当你说K必须实现IComparable时,会发生一些事情.在类型K的任何值上,您现在可以直接访问接口方法而无需强制转换,因为在程序中语义上它保证它将实现该接口.每当您尝试创建该类型的实例化时,编译器将检查您作为K参数提供的任何类型是否实现IComparable,否则您将收到编译时错误.或者,如果您使用反射进行操作,则会出现异常.

Bruce Eckel:你说的是编译器和运行时.

Anders Hejlsberg:编译器检查它,但您也可以在运行时使用反射进行检查,然后系统检查它.正如我之前所说,在编译时你可以做的任何事情,你也可以在运行时使用反射.