Pregunta

Estoy convirtiendo manualmente el código de Java a C # y luchando con (lo que llamo) tipos primitivos (véase, por ejemplo, Do autoboxing y se comportan de manera diferente unboxing en Java y C # ). De las respuestas entiendo que double (C #) y Double (C #) son equivalentes y double (C #) también se puede utilizar en contenedores, por ejemplo, como una clave en un diccionario. Sin embargo, double (Java) no se puede utilizar en contenedores como HashMap que es por eso que es automático en caja a Double (Java).

  1. ¿Es double (C #) una primitiva o un objeto?
  2. Si se trata de una primitiva lo que hace que se comporte de forma diferente a partir double (Java)?

double (C #) no se puede ajustar a nulo, a menos que se hace nullable.

  1. ¿Es double? (C #) equivalente a Double (Java)? Se refirieron tanto a como objetos?

(Es el uso del término "objeto de primera clase" útil en esta discusión?)

¿Fue útil?

Solución

Tanto C # y Java tienen primitivas (o "valor") tipos: int, double, float, etc ...

Sin embargo, después de este C # y Java tienden a dividir.

Java tiene envoltorio tipos de clase para todos los tipos primitivos (que es un pequeño conjunto finito en Java) que les permite ser tratados como objetos. double/Double, int/Integer, bool/Boolean, etc. Estos tipos de envoltura son de referencia tipos (es decir: Clases) y, como tal, null es un valor válido para asignar a dichas expresiones / variables de tipo. Las versiones recientes de Java (1.5 / 5 +) Agregar a coacciones implícitas de primitivas a su correspondiente envoltura.

// Java
Boolean b = true; // implicit conversion boolean -> Boolean (Java 5+)
Boolean b = null; // okay, can assign null to a reference type
boolean n = null; // WRONG - null is not a boolean!

C # no proporciona una una envoltura tan directa 1 - en parte, porque C # soporta un conjunto infinito de tipos de valor a través de estructuras ; más bien, C # asas "Tipos de valor" anulable por introducción de un Nullable<T> tipo envoltura. Además C #, como Java, tiene conversiones implícitas desde el tipo de valor T a Nullable<T>, con la restricción de que T es "no un tipo anulable" misma.

// C#
Nullable<bool> b = true; // implicit conversion bool -> bool?
bool? b = true;          // short type syntax, implicit conversion
bool? b = null;          // okay, can assign null as a Nullable-type
bool b = null;           // WRONG - null is not a bool

Nota que Nullable<T> es también un tipo de valor y por lo tanto sigue las reglas de estructura estándar para cuando / si un valor es "en la pila" o no.

En respuesta al comentario:

absolutamente correcto, Anulable ser un tipo de valor hace permitir que tenga una huella de memoria más compacto en ciertos casos ya que puede evitar la sobrecarga de memoria de un tipo de referencia: ¿Qué es la huella de la memoria de un anulable . Sin embargo, todavía requiere más memoria que el tipo no anulable porque tiene que recordar si el valor es, así, nula, o no. Dependiendo de los problemas de alineación y aplicación VM, esto puede o no puede ser significativamente menor que un objeto "lleno". Además, dado que los valores de C # / CLR están materializadas, a estudiar todas las operaciones de elevación que se deben realizar:

// C#
object x = null;
x = (bool?)true;
(x as bool?).Value // true

El artículo de Java Tip 130: ¿Cómo están sus datos tamaño? conversaciones sobre el consumo de memoria de tipo de referencia (en Java). Una cosa a destacar es que la JVM se ha especializado versiones de matrices internamente, uno para cada tipo primitivo y de objetos (sin embargo, tenga en cuenta que este artículo contiene algunas declaraciones engañosas ). Nota cómo los objetos primitivos (vs) incurrir en gastos indirectos de memoria adicional y los problemas de alineación de bytes. C # sin embargo, se puede extender el caso-array optimizado para este tipo de Nullable<T> vs. los los limitados especiales-casos, la JVM tiene porque Nullable<T> es en sí misma sólo un tipo de estructura (o "primitivo").

Sin embargo, un objeto, sólo requiere un pequeño tamaño fijo para mantener una "referencia" a ella en una ranura variable. Una ranura variable de tipo Nullable<LargeStruct> por otra parte, debe tener espacio para LargeStruct+Nullable (la ranura en sí puede ser en el montón). Ver C # Conceptos: Valor vs tipos de referencia . Nota cómo en el ejemplo "elevación" por encima de la variable es de tipo object: object es el "tipo de raíz" en C # (padre de ambos tipos de referencia y los tipos de valor) y no un tipo de valor especializado <. / p>


1 El lenguaje C # soporta un conjunto fijo de alias para los tipos primitivos / comunes que permiten el acceso a los nombres de tipo "amigable" en minúscula. Por ejemplo, double es un alias para System.Double y int es un alias para System.Int32. A no ser que un tipo diferente Double es importado en su alcance, double y Double se refieren al mismo tipo en C #. Recomiendo el uso de los alias menos que haya una razón para no hacerlo.

Otros consejos

Nullable<double> (también conocido como double?) en C # es no lo mismo que un Double en Java.

Antes de Java tenía autoboxing / unboxing, había que convertir manualmente entre primitivas y objetos de primera clase:

Double dblObj = new Double(2.0);
double dblPrim = dblObj.doubleValue();

En Java 1.5 que ha cambiado, por lo que sólo se podía hacer:

Double dblObj = 2.0;
double dblPrim = dblObj;

y Java sería insertar código para reflejar el ejemplo anterior de forma automática.

C # es diferente porque hay un número ilimitado de tipos "primitivos" (lo que las llamadas de CLR tipos de valor ). Estos se comportan igual que la mayoría de las primitivas de Java, utilizando semántica de valor . Se pueden crear nuevos tipos de valor utilizando la palabra clave struct. C # ha autoboxing / unboxing para todos tipos de valor, y también hace que todos los tipos de valores se derivan de Object.

Así que usted puede utilizar un tipo de valor (como double) donde utilizaría cualquier referencia a un objeto (por ejemplo, como una llave en una Dictionary) y será en caja, si es necesario, o bien simplemente utilizar directamente. (C # 's genéricos aplicación es lo suficientemente bueno para el boxeo evitar en la mayoría de las circunstancias.)

En C #, la mejor manera de objetos separados son por "Tipos de valor", que son un poco como los primitivos - ints, bools, etc y "Tipos de referencia" -. Clases, etc.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top