为什么 C# 泛型的专业化受到限制?

Why is specialization in C# generics limited?

问题对C#的泛型有评论:

Type information is maintained, which allows specialization to an extent, by examining type arguments using reflection. However, the degree of specialization is limited, as a result of the fact that a generic type definition is compiled before any reification happens (this is done by compiling the definition against the constraints on the type parameters - thus, the compiler has to be able "understand" the definition even in the absence of specific type arguments).

我相信意思如下:

当您定义泛型类型时,例如MyGenericType<T> 您的定义必须对 T 的任何值都有意义,因为泛型类型是在您在特定实现中实际使用它之前编译的 ("the degree of specialization is limited, as a result of the fact that a generic type definition is compiled before any reification happens")。

稍后,当您实际使用 MyGenericType<int> 时,compiler/jit 将创建一个新的 class,几乎 MyGenericType<T> 每次提到 T 替换为 int。这就是具体化的过程。这意味着在运行时,您可以使用泛型类型使用 int 的事实,但是您使用它(专业化)的能力是有限的,因为当您定义 MyGenericType<T> 时您并不知道这一点。

What does it mean by "specialization"? Is it not the same as instantiation of a generic type with a specific type argument?

作者在他的回答中专门针对 Java 泛型的部分解释说

specialization of a generic type [is] the ability to use specialized source code for any particular generic argument combination.

换句话说,如果泛型类型参数是特定类型,它就是一种做一些特殊事情的能力。当您将类型实例化为 List<bool> 时,提供 List<T> 的实现将单个元素表示为位将是专业化的一个示例。

What does it mean by "the degree of specialization is limited"?

作者的意思是虽然你可以这样写

if (typeof(T) == typeof(bool)) {
    ...
}

你响应类型参数组合的能力是有限的,因为任何关于类型组合的决定都必须在 运行 时间做出。

Why is it "a result of the fact that a generic type definition is compiled before any reification happens"?

因为具体化是在 CLR 中完成的,所以在 C# 编译器不在画面之后。编译器必须为 CLR 生成泛型类型定义,以用作 "template" 为泛型 class.

的实例创建封闭构造类型

专业化用作泛化的反义词。当您创建泛型类型时,您泛化了一个类型定义。当你用一个类型初始化它时,你专门化了编译的泛型类型,以便能够在 运行 时间创建该类型的对象。

IL 编译泛型。在 运行 时,此已编译泛型类型与特定类型参数组合以生成指定 class 的对象。

是的,特化与在 运行 时使用特定类型参数实例化泛型类型相同。

使用泛型,come constraints which basically fix the scope of generic type。您可以通过定义 T 可以是结构 class 或必须具有某些特定基数 class 等来判断。您不能创建约束不允许的 class 实例在通用类型上定义。

您可以使用 int、string 或其他 class 初始化相同的泛型类型定义,前提是它满足泛型 class 中的约束。 它不能直接用 T 创建 class 的对象,还没有被定义的类型(原始类型,如 int、string 或您的自定义 class 或接口)替换,并且您的代码内部应该兼容类型作为 T 传入以使其工作。

参考(来自上述相同问题的链接):

NET Generics and Code Bloat

Generics are not templates (as in C++)