什么是仿制药之间的C#和Java和模板在C ++的区别...? [英] What are the differences between Generics in C# and Java... and Templates in C++?

查看:106
本文介绍了什么是仿制药之间的C#和Java和模板在C ++的区别...?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我主要是使用Java和泛型是相对较新。我继续读了Java做出的错误决定或.NET具有更好的实现等等等等。

I mostly use Java and generics are relatively new. I keep reading that Java made the wrong decision or that .NET has better implementations etc. etc.

那么,什么是仿制药C ++​​,C#,Java之间的主要区别?优点/每个的利弊?

So, what are the main differences between C++, C#, Java in generics? Pros/cons of each?

推荐答案

我将添加我的声音噪声,并采取刺伤澄清事情:

I'll add my voice to the noise and take a stab at making things clear:

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

和则编译器将prevent你把东西并不到列表中。结果
幕后的C#编译器只是把后面列表&LT;人&GT; 到.NET的DLL文件,但在运行时JIT编译器去,并建立了一套新的code的,因为如果你写了一个特殊列表类只含人 - 像 ListOfPerson

and then the compiler will prevent you from putting things that aren't Person into the list.
Behind the scenes the C# compiler is just putting List<Person> into the .NET dll file, but at runtime the JIT compiler goes and builds a new set of code, as if you had written a special list class just for containing people - something like ListOfPerson.

这样做的好处是,它使得它非常快。有没有铸造或其他任何东西,因为这个DLL中包含这是,其他code,看起来它以后使用反射能的列表中的信息告诉它包含的对象(所以你得到智能感知等)。

The benefit of this is that it makes it really fast. There's no casting or any other stuff, and because the dll contains the information that this is a List of Person, other code that looks at it later on using reflection can tell that it contains Person objects (so you get intellisense and so on).

这样做的缺点是,旧的C#1.0和1.1 code(之前他们增加了仿制药)不理解这些新的列表&LT;东西&GT; ,所以你必须手动转换东西还给普通的旧式列表与他们进行互操作。这不是大问题,因为C#2.0的二进制code不是向后兼容。这将不会发生的唯一情况是,如果你要升级一些老的C#1.0 / 1.1 code到C#2.0

The downside of this is that old C# 1.0 and 1.1 code (before they added generics) doesn't understand these new List<something>, so you have to manually convert things back to plain old List to interoperate with them. This is not that big of a problem, because C# 2.0 binary code is not backwards compatible. The only time this will ever happen is if you're upgrading some old C# 1.0/1.1 code to C# 2.0

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

在表面上看起来是相同的,而且排序是。编译器也将prevent你把东西并不到列表中。

On the surface it looks the same, and it sort-of is. The compiler will also prevent you from putting things that aren't Person into the list.

的差异是在幕后发生什么。不像C#,Java没有去构建一个特殊的 ListOfPerson - 它只是采用了普通的旧的ArrayList 这一直在Java中。当你得到的东西出数组中,通常者P =(人)foo.get(1); 铸造舞蹈仍然有许多工作要做。编译器节约了您的键盘presses,但速度命中/铸造仍在发生,就像它始终是。结果
当人们提到类型擦除这是他们在说什么。编译器插入蒙上了你,然后'清除'的事实,它的意思是而不仅仅是对象

The difference is what happens behind the scenes. Unlike C#, Java does not go and build a special ListOfPerson - it just uses the plain old ArrayList which has always been in Java. When you get things out of the array, the usual Person p = (Person)foo.get(1); casting-dance still has to be done. The compiler is saving you the key-presses, but the speed hit/casting is still incurred just like it always was.
When people mention "Type Erasure" this is what they're talking about. The compiler inserts the casts for you, and then 'erases' the fact that it's meant to be a list of Person not just Object

这种方法的好处是,老code不明白仿制药没有在意。它仍然同样的老处理的ArrayList ,因为它总是有。这是在Java世界,因为他们想支持编译使用Java 5泛型code更重要的,有它的老1.4或previous JVM的,微软故意决定不打扰运行。

The benefit of this approach is that old code which doesn't understand generics doesn't have to care. It's still dealing with the same old ArrayList as it always has. This is more important in the java world because they wanted to support compiling code using Java 5 with generics, and having it run on old 1.4 or previous JVM's, which microsoft deliberately decided not to bother with.

缺点是我所提到的速度击中previously,也因为没有 ListOfPerson 伪类之类的东西进入的.class文件, code,看起来它以后(与反思,或者如果你拉出来另外一个集合,其中它被转换成的对象或等)不能告诉以任何方式,它的意思是只包含一个List ,不是任何其他数组列表。

The downside is the speed hit I mentioned previously, and also because there is no ListOfPerson pseudo-class or anything like that going into the .class files, code that looks at it later on (with reflection, or if you pull it out of another collection where it's been converted into Object or so on) can't tell in any way that it's meant to be a list containing only Person and not just any other array list.

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

它看起来像C#和Java泛型,它会做什么你认为它应该做的,但幕后不同的事情正在发生。

It looks like C# and Java generics, and it will do what you think it should do, but behind the scenes different things are happening.

它拥有的最常见的用C#泛型它建立特殊的伪类,而不是仅仅丢掉像Java的确类型的信息,但它是一个完全不同鱼的烧水壶。

It has the most in common with C# generics in that it builds special pseudo-classes rather than just throwing the type information away like java does, but it's a whole different kettle of fish.

两个C#和Java产生输出被设计为虚拟机。如果你写一些code这中有一个类,在这两种情况下,有关的一些信息类将进入该.dll或.class文件,以及JVM / CLR会做的东西与此有关。

Both C# and Java produce output which is designed for virtual machines. If you write some code which has a Person class in it, in both cases some information about a Person class will go into the .dll or .class file, and the JVM/CLR will do stuff with this.

C ++产生的原始二进制86 code。一切的的对象,并且有哪些需要了解一个类没有基础的虚拟机。有没有拳击或拆箱和功能没有属于类,或者确实什么。

C++ produces raw x86 binary code. Everything is not an object, and there's no underlying virtual machine which needs to know about a Person class. There's no boxing or unboxing, and functions don't have to belong to classes, or indeed anything.

由于此,C ++编译器的地方您可以用模板做任何限制 - 基本上任何code,你可以手工编写,就可以得到模板为你写结果。
最明显的例子是添加的东西:

Because of this, the C++ compiler places no restrictions on what you can do with templates - basically any code you could write manually, you can get templates to write for you.
The most obvious example is adding things:

在C#和Java泛型系统需要知道哪些方法可用于一类,它需要通过这个下到虚拟机。告诉它这一点的唯一方法是要么硬编码的实际类,或使用接口。例如:

In C# and Java, the generics system needs to know what methods are available for a class, and it needs to pass this down to the virtual machine. The only way to tell it this is by either hard-coding the actual class in, or using interfaces. For example:

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

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

That code won't compile in C# or Java, because it doesn't know that the type T actually provides a method called Name(). You have to tell it - in C# like this:

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

然后,你必须确保你传递给addNames的事情实现了IHasName接口等。 java的语法是不同的(&LT;吨延伸IHasName&GT; ),但它从同一个问题的困扰。

And then you have to make sure the things you pass to addNames implement the IHasName interface and so on. The java syntax is different (<T extends IHasName>), but it suffers from the same problems.

有关这个问题的'经典'的情况下试图写一个函数,它做到这一点。

The 'classic' case for this problem is trying to write a function which does this

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

因为没有办法申报与 + 在其方法的接口你不能真正写code。你失败了。

You can't actually write this code because there are no ways to declare an interface with the + method in it. You fail.

C ++从没有这些问题困扰。编译器不关心类型传递到任何虚拟机 - 如果你的两个对象有一个.Name点()函数,它会编译。如果他们不这样做,它不会。简单的。

C++ suffers from none of these problems. The compiler doesn't care about passing types down to any VM's - if both your objects have a .Name() function, it will compile. If they don't, it won't. Simple.

所以,你有它: - )

So, there you have it :-)

这篇关于什么是仿制药之间的C#和Java和模板在C ++的区别...?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆