Question

Je suis le code de Java manuellement la conversion en C # et aux prises avec (ce que j'appelle) les types primitifs (voir, par exemple Do autoboxing et se comportent différemment unboxing en Java et C # ). D'après les réponses que je comprends que double (C #) et Double (C #) sont équivalentes et double (C #) peut également être utilisé dans des conteneurs, par exemple comme une clé dans un dictionnaire. Cependant, double (Java) ne peut pas être utilisé dans des conteneurs comme HashMap qui est pourquoi il est auto-boxed à Double (Java).

  1. est double (C #) une primitive ou un objet?
  2. Si c'est un primitif ce qui fait qu'il se comporte différemment de double (Java)?

double (C #) ne peut pas être définie sur null si elle est faite nullable.

  1. est double? (C #) équivalent à Double (Java)? Sont-ils tous les deux désignés comme des objets?

(L'utilisation du terme « objet de première classe » utile dans cette discussion?)

Était-ce utile?

La solution

C # et Java ont primitive (ou "valeur") types: int, double, flotteur, etc ...

Cependant, après cette C # et Java ont tendance à se diviser.

Java a wrapper types de classe pour tous les types primitifs (ce qui est un petit ensemble fini en Java) qui leur permet d'être traités comme des objets. double/Double, int/Integer, bool/Boolean, etc. Ces types d'enveloppe sont types-référence (lire: classes) et, en tant que tels, null est une valeur valide pour attribuer à ces expressions tapées / variables. Les versions récentes de Java (1.5 / 5 +) ajouter à coercitions implicites de primitives à leur emballage correspondant.

// 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 # ne fournit pas une telle enveloppe directe 1 - en partie parce que C # prend en charge un ensemble infini de types de valeurs via structures ; plutôt, C # gère "types de valeur nullables" par l'introduction d'un Nullable<T> le type d'emballage. De plus C #, comme Java, a des conversions implicites du type de valeur T à Nullable<T>, avec la restriction que T est lui-même "pas un type nullable".

// 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

Notez que Nullable<T> est également un type de valeur et suit ainsi les règles de structure standard pour quand / si une valeur est « sur la pile » ou non.

En réponse au commentaire:

Tout à fait correct, Nullable étant une valeur de type ne lui permet d'avoir une empreinte mémoire plus compact dans certains cas car il peut éviter la surcharge de la mémoire d'un type de référence: Quelle est l'empreinte mémoire d'un Nullable . Cependant, il nécessite encore plus de mémoire que le type non Nullable parce qu'il doit se rappeler si la valeur est, bien, nulle ou non. En fonction des problèmes d'alignement et la mise en œuvre VM, cela peut ou peut ne pas être significativement inférieur à un objet « plein ». En outre, étant donné que les valeurs en C # / CLR sont réifiées, tenez compte des opérations de levage qui doivent être effectuées:

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

L'article Conseil Java 130: Connaissez-vous vos données taille? talks sur la consommation de mémoire de type de référence (en Java). Une chose à noter est que la machine virtuelle Java a des versions spécialisées de tableaux en interne, un pour chaque type primitif et pour les objets (cependant, s'il vous plaît noter que cet article contient une déclarations trompeuses ). Notez comment les objets (par rapport aux primitives) une surcharge du mémoire supplémentaire et les problèmes d'alignement d'octets. C # cependant, peut prolonger le cas matrice optimisée pour les types de Nullable<T> contre les spéciales les-cas limités parce que la machine virtuelle Java a Nullable<T> lui-même est seulement un type de structure (ou « primitifs »).

Cependant, un objet, ne nécessite qu'une petite taille fixe pour maintenir une « référence » dans une fente variable. Une fente variable de type Nullable<LargeStruct> d'autre part, doit disposer d'un espace pour LargeStruct+Nullable (la fente elle-même peut être sur le tas). Voir C # Concepts: Valeur vs Types de référence . Notez comment dans l'exemple « de levage » au-dessus de la variable est de type object. object est le « type racine » en C # (parent des deux types de référence et les types de valeurs) et pas un type de valeur spécialisée


1 Le langage C # prend en charge un ensemble fixe de alias pour primitifs / types communs qui permettent d'accéder aux noms de type "minuscule" convivial. Par exemple, double est un alias pour System.Double et int est un alias pour System.Int32. À moins qu'un autre type de Double est importée portée, double et Double se référeront au même type en C #. Je recommande d'utiliser les alias moins qu'il y ait une raison de faire autrement.

Autres conseils

Nullable<double> (alias double?) en C # est pas même comme Double en Java.

Avant de Java avait autoboxing / unboxing, il fallait convertir manuellement entre les primitives et les objets de première classe:

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

Dans Java 1.5 qui a changé, vous pouvez donc faire:

Double dblObj = 2.0;
double dblPrim = dblObj;

Java insérerait code pour refléter l'exemple ci-dessus automatiquement.

C # est différent parce qu'il ya un nombre illimité de types "primitifs" (ce que les appels CLR types de valeur ). Ceux-ci se comportent comme la plupart des primitives de Java, en utilisant la sémantique de valeur . Vous pouvez créer de nouveaux types de valeur en utilisant le mot-clé struct. C # a autoboxing / unboxing pour tous types de valeur, et rend également tous les types de valeurs dérivent de Object.

Vous pouvez donc utiliser un type de valeur (comme double) où vous utiliseriez une référence d'objet (par exemple, comme une clé dans un Dictionary) et il sera si nécessaire boxed, ou bien juste utilisé directement. (Mise en œuvre Génériques de C # est assez bon pour éviter la boxe dans la plupart des cas.)

En C #, la meilleure façon d'objets séparés sont par "Value Types" qui sont un peu comme primitives - ints, bools, etc et "Types de référence" -. Classes etc

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top