小编典典

C ++模板和Java / C#泛型之间的区别是什么?限制是什么?

java

我从这里阅读了一篇有趣的文章/主题/讨论,并且遇到了以下问题:

  • Java / C#泛型的局限性是什么?
  • C ++模板有什么功能,而Java / C#泛型则没有呢?

编辑1 Eric Lippert推荐的其他问题

  • C#泛型可能有哪些模式,而C ++模板却没有?
  • C#的真实泛型类型和Java的类型擦除泛型类型之间有什么区别?

阅读 208

收藏
2020-11-13

共1个答案

小编典典

首先,您可能想阅读我在2009年关于该主题的文章

在我看来,C 模板和C#泛型之间的主要区别在于,C 模板实际上 在构建 模板时就 完全重新编译了代码 。C ++方法的优缺点很多:

  • PRO:您可以有效地创建约束,例如“类型参数T必须具有加法运算符”;如果代码中包含彼此相加的两个T,则如果您使用不允许加法的类型参数构造模板,则模板将无法编译。

  • 缺点:您可能会意外地创建未记录的约束,例如“类型参数T必须具有加法运算符”。

在C#中,您必须 说出 什么约束对用户有帮助,但是您只限于一小部分可能的约束:接口,基类,值与引用类型以及默认构造函数约束,仅此而已。

  • 优点:两种不同结构的语义分析可能完全不同。如果您想要那样,那就太好了。

  • 缺点:对于两种不同的结构,语义分析可能完全不同。如果您不希望那样,那就是一个等待发生的错误。

在C#中,无论构造类型多少次,语义分析都会进行 一次 ,因此需要使用 任何 满足约束的类型实参,而不仅仅是实际提供的类型实参。

  • PRO:您只为需要的构造生成代码。

  • 缺点:您为所有使用的构造生成代码。

模板会导致代码生成变大。在C#中,只生成一次泛型类型的IL,然后在运行时抖动为程序使用的所有类型进行代码生成。这具有很小的性能成本,但是由于抖动实际上对于
所有引用类型参数
仅生成一次代码,因此可以在一定程度上缓解这种情况。因此,如果您有List<object>List<string>则抖动代码仅生成一次,并用于两者。List<int>List<short>由对比度即时编译的代码的两倍。

  • PRO:使用模板库时,您就可以在其中找到源代码。

  • 缺点:要使用模板库,您必须具有源代码。

在C#中,泛型是一流的类型。如果将它们粘贴在库中,则可以在任何地方使用该库而不必附带源代码。

最后:

  • PRO:模板允许模板元编程。

  • 缺点:新手很难理解模板元编程。

  • 缺点:模板系统实际上不允许在通用系统中非常简单的某些类型拓扑。

例如,我想在C ++中很难做到这样:

class D<T> 
{
    class S { }
    D<D<T>.S> ds;
}

在C#泛型中,没问题。在运行时,仅对所有引用类型参数构建 一次 该类型。

但是,在C++模板中,拥有后会发生什么D<int>?内部类型构造一个type的字段D<D<int>.S>,因此我们需要构造该类型。但是该类型构造了一个类型为D<D<D<int>.S>.S>…的字段,依此类推直至无穷大。

2020-11-13