C# 泛型 : does compiler creates only one specialized generic type for different reference types?

标签 c# generics

Generics in the Run Time (C# Programming Guide)据说确实如此,这让我感到惊讶。我一直认为,在幕后它会为每个不同的类型参数创建一个单独的专用类型,无论它是值类型还是引用类型。也许是因为(如果我没记错的话)我使用 C++ 时就是这样的。

无论如何,我无法理解如果 C# 编译器将所有引用类型都视为一个专用泛型类中的指针,那么它如何知道它所处理的类型。例如,当 List<T>返回一个项目,它应该知道它返回哪种类型,因此应该有一个专门的方法/类。它到底如何运作?它是否仅为系统通用集合或任何通用类(包括自定义类)创建单个专用类型?

最佳答案

我想回答得更深一点。

首先,让我们问这个问题。

How CLR treats with generic method?

当使用泛型类型参数的方法进行 JIT 编译时,CLR 会采用该方法的 IL,替换指定的类型参数,然后创建特定于该方法对指定数据类型进行操作的 native 代码。这称为代码爆炸

In which way does CLR generate that native code? Is there any rules?

CLR 不断为每个方法/类型组合生成 native 代码。如果任何类型参数是值类型,则 CLR 必须生成专门针对该值类型的 native 代码。原因是因为值类型的大小可能会有所不同。

但是,对于引用类型CLR 有一些优化。 CLR 认为所有引用类型参数都是相同的。同样,代码可以共享。例如,CLR 编译的代码为 List<String>的方法可用于List<Stream>的方法,因为 StringStream都是引用类型。事实上,对于任何引用类型,都会使用相同的代码。 CLR 可以执行此优化,因为所有引用类型参数或变量实际上只是指针。

该解释的来源是 Jeffrey Ritcher 的书。 (CLR via C#)

现在我们来回答你的问题:

I can't understand how the C# compiler knows what type it deals with?

正如您所知,CLR 使用指针作为引用类型泛型参数。当然,该指针指向堆上的某个对象。堆上的每个对象都需要一些额外的成员。其中之一称为类型对象指针。并且该指针指向相应的Type存储在堆上的对象。并且,CLR 使用该信息来获取对象的类型。

关于C# 泛型 : does compiler creates only one specialized generic type for different reference types?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59600466/

相关文章:

c# - EDML 生成模型的代码在哪里?

c# - 备份和恢复只是一张表?

c# - 如何从c#代码中调用java中的方法?

c# - 枚举双向搜索的用户界面设计

KProperty1.getDelegate 上的泛型过于严格?

java - 重构泛型

c# 在回调中调用 endinvoke,使用泛型

ios - Swift 4 - 通用类型转换问题 - 无法转换为预期类型 '(_) -> Void'

c# - 调用数据访问层的通用方法

C# - 正则表达式替换(如果不在引号内)