非泛型类的C#泛型方法归结为什么?

Isa*_*ham 11 c# generics reification

如果我有这样的课: -

static class Foo {
   public static void Bar<T>(T item) { Console.WriteLine(item.ToString(); }
}
Run Code Online (Sandbox Code Playgroud)

我知道在这个例子中没有必要使用T,因为所有的类型都有ToString()等等 - 这只是一个人为的例子.我更感兴趣的是在发动机罩下发生的事情如下: -

Foo.Bar("Hello");
Foo.Bar(123);
Foo.Bar(new Employee("Isaac"));
Run Code Online (Sandbox Code Playgroud)

我广泛地(想想!)我理解具体化,即如果你制作不同类型的泛型类,例如

List<Int32>
List<String>
List<Employee>
Run Code Online (Sandbox Code Playgroud)

然后在编译时(或运行时?)我们最终会得到三个实际的具体类型,每个类型对应一个指定的泛型参数.在我的第一个例子中是否同样适用于方法调用,即我们是否仍然有一个类Foo但是有三个Reified Bar方法,一个用于String,Int32和Employee?

Ken*_*rey 3

这就是 C++ 模板和 C# 泛型之间的区别发挥作用的地方。

在 C++ 中,模板会为其使用的每种类型生成一个新方法。然而,在 C# 中,方法中的代码仅创建一次。无论您使用intstringobject类型参数调用它,都会运行相同的代码。

由于 C# 泛型在编译时保持泛型,因此它们可以在已编译的库中公开,而无需重新编译。在 C++ 中,您需要在使用代码中包含原始模板,以便可以编译新的副本。

简而言之,每个泛型方法只能获得一个已编译的方法。

  • 不过,“编译”变得很棘手;在IL水平上是正确的;在JIT级别,可以有多个“已编译”实现——因此这取决于“已编译”的确切含义。AOT 编译器通常会立即生成“n”个方法,用于“n”个不同的用途。 (2认同)
  • 好的 - 我对运行时的角度更感兴趣 - 听起来你在运行时为引用类型版本获得一个实例,并为每种不同的值类型获得一个实例,或多或少? (2认同)