2010-11-20 22 views

Respuesta

28

C# tiene un sistema de tipo unificado. Todos los tipos C#, incluyendo tipos primitivos como int y double, heredan de una única raíz object tipo. A diferencia de los objetos de clase, estos tipos primitivos son tipos de valor. No se asignan por separado al montón, y se pasan por valor.

Cuando se coloca un tipo de valor C# (como una estructura primitiva int, o estructura definida por el usuario) en una colección paramétrica, se almacena en una matriz densamente empaquetada sin punteros. Esto es posible porque C# realiza una instanciación paramétrica personalizada para cada "tamaño" paramétrico diferente que se requiera. Esto significa que al crear una instancia de C# List<int>, la lista de matriz subyacente almacena arrays densamente empaquetados de int.

Fuente: http://www.pin5i.com/showtopic-24376.html

Java también tiene varios tipos primitivos (int, long, double, byte, etc.) - sin embargo, son especiales ya que son no orientado a objetos y no se pudo haber definido usando el lenguaje mismo. Son tipos de valor, no asignados en pila, y pasados ​​por valor.

Fuente: Comparison of C# and Java - Unified type system (Wikipedia)

Al mismo tiempo, Java también tiene orientadas a objetos primitivos "envoltura" tipos (Entero, Largo, Doble, byte, etc.), a menudo llamados tipos boxed. Estos son objetos asignados en el montón que se pasan por referencia, y existen en paralelo a los tipos primitivos mencionados anteriormente.

En versiones más recientes de Java, los tipos primitivos se encapsulan automáticamente en tipos de objetos cuando es necesario. Esto alivia la mayor parte de la carga de administrarlos, pero también puede causar errores sutiles (consulte también auto-boxing).

En contraste con C#, en Java, el marco de colecciones JDK incorporado siempre administra las colecciones de punteros de objeto. Para hacerlos paramétricos de manera compatible con versiones anteriores, Java realiza una técnica llamada borrado de tipos, donde (durante el tiempo de ejecución) todo se trata como un objeto dentro del contenedor (las comprobaciones de tipos parametrizadas se realizan en tiempo de compilación).

Esto significa que no puede hacer una Java List<int>, solo puede hacer List<Integer>. Y, la lista anterior en realidad almacena una matriz de punteros a los objetos Integer en caja, que es el doble del tamaño y sustancialmente menos rendimiento que la versión C#. Para la mayoría de los casos de uso, esta diferencia de tamaño y rendimiento es irrelevante.

En casos de uso donde el tamaño y el rendimiento son relevantes, hay dos opciones disponibles:

  1. Cuando se conoce el tamaño de su lista de antemano, utilizar una matriz de tipos nativos, por ejemplo int[]. Las matrices de tipos nativos están empaquetadas en la memoria, por lo que consumen MUCHA memoria y son más eficientes.
  2. Cuando no se conoce el tamaño de su lista de antemano, utiliza algún implementación de la lista tercera parte que envuelve la matriz nativa, por lo que es posible añadir elementos a ella después de la creación (algunos ejemplos: Trove, Colt, Fastutil, Guava) .
+0

Leí, una vez, un proyecto de la Universidad, donde un lenguaje de programación usaba un sistema de tipo unificado, con tipos primitivos y objetos, pero, los tipos primitivos tenían una herencia oculta, y el objeto base y los tipos primitivos, donde subclases de un tipo de raíz oculto – umlcat

+0

lol, suena muy familiar, lo que sucedió con este proyecto umlcat lol – brumScouse

+0

@brumScouse: No lo sé. Perdí el enlace. Empecé a aplicar lo que aprendí, en un proyecto de mascota personalizado. Ambos, Java y C# no son solo objetos progresivos. lang., y creo que está bien tener tipos primitivos, y un sistema de tipo unificado, que es independiente de la Orientación del objeto. – umlcat

12

Esto tampoco es cierto para C#, no todos los tipos se derivan de los objetos, al igual que el 99.9% de ellos. Existen un par de tipos muy extraños que no pueden convertirse en objetos. El único soportado oficialmente es punteros. Hay 3 más no soportados como TypedReference, RuntimeArgumentHandle y un tercero cuyo nombre se me escapa. Esos 3 tipos se utilizan con interoperabilidad con métodos de longitud variable en C++/C. No me preocuparía demasiado por ellos.

+0

Fue una pérdida de nervios explorar los detalles de este mito [aquí] (https://blogs.msdn.microsoft.com/ericlippert/2009/08/06/not-everything-derives-from-object/) ¿Pudiste para descubrir el tercer tipo no compatible? Por cierto, incluso los punteros no son compatibles hasta que los lances al tipo de valor 'System.IntPtr' o' System.UIntPtr'. – RBT