繁体   English   中英

C#编译器如何与泛型一起使用?

[英]How does the C# compiler work with generics?

在C ++中, template声明需要在头文件中(除非您明确声明模板类型),我明白了解原因。

我没有得到的是如果C#编译器没有要检查的.cs文件,它如何处理泛型。 我怀疑它会检查CIL,因为这将是一个处理器密集型操作。 我知道它能够从元数据中提取类型信息,但是如果通用函数的代码也被编码,那么对于可执行文件来说这将是一个巨大的膨胀。

那么,再次,编译器如何使用泛型?

我想你问的是C#编译器如何使用引用程序集中定义的泛型类型,而不是询问C#编译器如何编译定义泛型类型的.cs文件(因为你说“如果它没有.cs文件“)。

通用类型和成员在IL中编码为通用。 封闭的泛型类型和成员由jit编译器在运行时构造。 所以对你的问题的简单回答是“C#编译器通过发出IL来处理泛型类型,导致jit编译器在运行时构造它们。”

C#编译器从程序集中读取有关类型的元数据,无需查看IL。 您可以使用反射编写类似的代码来分析泛型类型。

C#编译器也没有理由查看方法的内部实现。

请检查C#和Java中的泛型和C ++中的模板之间有什么区别? 和类似的搜索结果 ,因为C#不需要知道方法的实现(与C ++不同) - C#中的所有约束都是从类/方法签名中得知的,这与C ++模板不同,其中类型只需要匹配body内使用的方法的名称。

让我试着清理一下......

泛型存储为IL,包括元数据中的参数和约束。 泛型类型也是类型,它们在运行时转换为运行时类型。 这是与C ++的主要区别,其中模板类型不存在,但只有派生类型; 在C#中,泛型类型存在于DLL中,但派生类型不存在(直到它们在运行时创建)。

但是,编译器确实做了一些事情。 例如,如果你有一个List.Add(T),那么IL中的签名就是那个。 但是,如果您调用它,它将使用List.Add(Foo)作为方法解析方法。 例如,在您的IL中,它将显示类似的内容(加载字段时):

ldfld class [mscorlib]System.List`1<Foo> Bar::variable

请注意,'Foo'在这里,而不是'T'。

此外,如果在泛型定义中对T进行约束,则会根据元数据检查它们的编译时间。

在这一点上,我想指出一些完全不同但相关的东西。 C#通过延迟生成类型(通常)获得性能。 这与C ++也有很大不同。 如果您尝试使用静态构造函数以及何时调用它们,您可以看到这一点。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM