C# 泛型:编译器是否只为不同的引用类型创建一个专用泛型类型?



在运行时泛型(C#编程指南(中,据说它确实如此,这让我感到惊讶。我一直认为,在后台,它会为每个不同的类型参数创建一个单独的专用类型,无论它是值还是引用类型。也许是因为(如果我没记错的话(当我使用它时,C++就是这样。

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

我想深入地回答一下。

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

CLR 如何使用泛型方法进行处理?

当使用泛型类型参数的方法进行 JIT 编译时,CLR 将获取该方法的 IL,替换指定的类型参数,然后创建特定于对指定数据类型进行操作的方法的本机代码。它被称为代码爆炸

CLR 以何种方式生成本机代码?有什么规则吗?

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

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

这种解释的来源是杰弗里·里彻(Jeffrey Ritcher(的书。(CLR 通过 C#(

现在我们归结为你的问题:

我不明白 C# 编译器如何知道它处理什么类型?

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

最新更新