C#中的泛型与Java …和C ++中的模板有什么区别?

问题:

我大多使用Java和泛型是比较新的。我继续阅读Java做错了决定,或者.NET有更好的实现等。
那么C ++,C#,Java在泛型中的主要区别是什么?每个优点/缺点?

回答:

我会给我的声音添加声音,并采取刺激来清除事情:

C#泛型允许你声明这样的东西。

List<Person> foo = new List<Person>();

然后编译器会阻止你将不是Person的东西放入列表中。
幕后,C#编译器只是将List<Person>放入.NET dll文件中,但在运行时,JIT编译器将会创建一组新的代码,就像您已经编写了一个专门用于包含人员的列表类ListOfPerson
这样做的好处就在于它使它变得非常快。没有任何投射或任何其他的东西,并且由于dll包含这是Person的列表的信息,其他代码后来使用反射可以看出它包含Person对象(所以你得到智能感知和所以)
这样做的缺点是旧的C#1.0和1.1代码(在他们添加泛型之前)不了解这些新的List<something>,所以你必须手动将东西转换为纯旧的List与之互操作。这不是一个大问题,因为C#2.0二进制代码不是向后兼容的。如果您将一些旧的C#1.0 / 1.1代码升级到C#2.0,那么唯一的时间将会发生

Java泛型允许你声明这样的东西。

ArrayList<Person> foo = new ArrayList<Person>();

在表面上它看起来是一样的,它的排序是。编译器也会阻止你把不属于Person的东西放在列表中。
不同之处在于幕后发生的情况。与C#不同,Java不会去构建一个特殊的ListOfPerson,它只是使用一直以来都是Java的普通旧的ArrayList。当你把东西从阵列中取出时,通常的Person p = (Person)foo.get(1);舞蹈仍然要做。编译器正在为您节省按键,但是速度的投射还是像往常一样发生。
当人们提到“类型擦除”时,这是他们正在谈论的。编译器会为您插入演员,然后“删除”这个事实,即它不仅仅是Object的列表Person
这种方法的好处是不明白泛型的旧代码不必关心。它仍然处理与旧的ArrayList一样。这在java世界中更为重要,因为他们希望支持使用Java 5编译代码,并使其具有泛型,并运行在旧的1.4或以前的JVM上,微软有意决定不要麻烦。
缺点是我以前提到的速度,也是因为没有ListOfPerson伪类或类似于.class文件的代码,稍后看的代码(反思或者如果你拉出来)的另一个集合,它被转换为Object等等)不能以任何方式说明它只是一个只包含Person而不仅仅是其他数组列表的列表。

C ++模板允许你声明这样的东西

std::list<Person>* foo = new std::list<Person>();

它看起来像C#和Java泛型,它会做你认为应该做的,但在幕后不同的事情发生。
它与C#泛型最相似,因为它构建了特殊的pseudo-classes,而不是像java那样抛出类型信息,但它是一个完全不同的水壶。
C#和Java都产生为虚拟机设计的输出。如果你写了一些包含Person类的代码,在这两种情况下,一些关于Person类的信息将进入.dll或.class文件,JVM / CLR将会做这些事情。
C ++生成原始x86二进制代码。一切都是not一个对象,没有底层的虚拟机需要知道一个Person类。没有拳击或拆箱,功能不一定属于课堂,甚至任何东西。
因此,C ++编译器对您可以使用模板做什么没有任何限制 – 基本上可以手动编写任何代码,您可以获取为您编写的模板。
最明显的例子是添加东西:
在C#和Java中,泛型系统需要知道什么方法可用于类,并且需要将其传递给虚拟机。告诉它的唯一方法是通过硬编码实际的类或使用接口。例如:

string addNames<T>( T first, T second ) { return first.Name() + second.Name(); }

该代码不会在C#或Java中编译,因为它不知道类型T实际上提供了一个名为Name()的方法。你必须告诉它 – 在C#这样:

interface IHasName{ string Name(); };
string addNames<T>( T first, T second ) where T : IHasName { .... }

然后你必须确保你传递给addNames的东西实现IHasName接口等等。 java语法是不同的(<T extends IHasName>),但它也有同样的问题。
这个问题的“经典”案例是试图写一个这样做的功能

string addNames<T>( T first, T second ) { return first + second; }

您无法实际编写此代码,因为没有办法使用+方法声明接口。你失败了。
C ++没有这些问题。编译器不关心将类型传递给任何虚拟机 – 如果您的对象都有.Name()函数,它将被编译。如果不这样做,那就不行了。简单。
所以你有它 :-)

 
 
Code问答: http://codewenda.com/topics/python/
Stackoverflow: What are the differences between Generics in C# and Java… and Templates in C++?

*转载请注明本文链接以及stackoverflow的英文链接

发表评论

电子邮件地址不会被公开。 必填项已用*标注

+ 1 = 4