Pergunta

Eu sou manualmente conversão de código de Java para C# e a lutar com os (que eu chamo) de tipos primitivos (ver, por exemplo, Fazer o autoboxing e unboxing se comportam de maneira diferente em Java e C#).A partir das respostas eu entendo que double (C#) e Double (C#) são equivalentes e double (C#) pode também ser usado em recipientes, por exemplo,como uma chave em um Dicionário.No entanto, double (Java) não pode ser usado em recipientes como HashMap é por isso que é auto-box para Double (Java).

  1. É double (C#) primitivo ou um objeto?
  2. Se é uma primitiva que o faz comportar-se de forma diferente a partir de double (Java)?

double (C#) não pode ser definido como null, a menos que ela é feita nullable.

  1. É double? (C#), equivalente a Double (Java)?São ambos referidos como objetos?

(É o uso do termo "primeira-classe de objeto" útil nesta discussão?)

Foi útil?

Solução

C# e Java primitivos (ou "valor") tipos:int, double, float, etc...

No entanto, após isso, C# e Java tendem a dividir-se.

Java tem Classe de wrapper tipos de todos os tipos primitivos (que é um pequeno conjunto finito em Java) que lhes permite ser tratado como Objeto.double/Double, int/Integer, bool/Boolean, etc.Estes wrapper tipos de referência-tipos (leia:Classes) e, como tal, null é um valor válido para atribuir a tais digitado expressões/variáveis.Versões mais recentes de Java (1.5/5+) adicionar na implícito coerções do primitivos correspondentes wrapper.

// 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# não fornece um tal direta de moldagem1 - em parte, porque o C# suporta um conjunto infinito de tipos de valor via estruturas;ao invés, C# alças "de valor nulo tipos" pela introdução de um Nullable<T> wrapper tipo.Além de C#, como Java, tem implícito conversões de tipo de valor T para Nullable<T>, com a restrição de que T não é "um tipo anulável" em si.

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

Note que Nullable<T> também é um tipo de valor e, portanto, segue a estrutura padrão de regras para quando/se o valor for "na pilha" ou não.

Em resposta ao comentário:

Absolutamente correto, Anulável sendo um tipo de valor não lhe permitem ter um mais compacto espaço de memória em certos casos, como ele pode evitar a sobrecarga de memória de um tipo de referência: O que é o espaço de memória de um Nullable<T>.No entanto, ele ainda requer mais memória do que o tipo não-Nulo, porque ela tem que se lembrar se o valor é, também, nulo, ou não.Dependendo de problemas de alinhamento e de implementação de VM, isso pode ou não pode ser significativamente menor do que um objeto "completa".Também, uma vez que os valores em C#/CLR são reificadas, considere quaisquer operações de içamento que devem ser executadas:

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

O artigo Java Dica 130:Você conhece o seu tamanho de dados? fala sobre o tipo de referência do consumo de memória (em Java).Uma coisa a notar é que a JVM tem versões especializadas de Matrizes internamente, um para cada tipo primitivo, e para Objetos (no entanto, por favor note que este artigo contém algumas declarações enganosas).Observe como os Objetos (vs.primitivos) implicam sobrecarga de memória e o alinhamento de byte problemas.C# no entanto, pode estender as otimizado-matriz de caso para Nullable<T> tipos de vs.o especial limitada-casos a JVM tem porque Nullable<T> é só por si um tipo de estrutura (ou "primitivos").

No entanto, um Objeto, requer apenas um pequeno tamanho fixo para manter uma "referência" a-lo em uma variável de fenda.Uma variável de fenda do tipo Nullable<LargeStruct> por outro lado, deve ter espaço para LargeStruct+Nullable (o entalhe em si, pode ser no heap).Ver C# Conceitos:Valor vs Tipos de Referência.Note-se como a "elevação" exemplo acima, a variável é do tipo object: object é o "tipo de raiz" em C# (pai de tipos de referência e tipos de valor) e não especializado tipo de valor.


1 A linguagem C# suporta um conjunto fixo de aliases para o primitivo/tipos comuns que permitem o acesso a "amigável minúsculas" nomes de tipo.Por exemplo, double é um alias para System.Double e int é um alias para System.Int32.A menos que o Double tipo de importados no escopo, double e Double vai se referir ao mesmo tipo em C#.Eu recomendo o uso de aliases, a menos que haja uma razão para fazer o contrário.

Outras dicas

Nullable<double> (também conhecido como double?) em C# é não o mesmo que um Double em java.

Antes de Java ter autoboxing/unboxing, você precisava converter manualmente entre primitivos e objetos de primeira classe:

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

No Java 1.5, isso mudou, para que você possa fazer:

Double dblObj = 2.0;
double dblPrim = dblObj;

E Java inseriria o código para refletir o exemplo acima automaticamente.

C# é diferente porque há um número ilimitado de tipos "primitivos" (o que o CLR chama Tipos de valor). Estes se comportam principalmente como os primitivos de Java, usando semântica de valor. Você pode criar novos tipos de valor usando o struct palavra -chave. C# possui autoboxing/unboxing para tudo tipos de valor e também faz com que todos os tipos de valor derivem de Object.

Então você pode usar um tipo de valor (como double) onde você usaria qualquer referência de objeto (por exemplo, como uma chave em um Dictionary) e será encaixotado, se necessário, ou apenas usado diretamente. (A implementação dos genéricos de C#é boa o suficiente para evitar o boxe na maioria das circunstâncias.)

Em C#, a melhor maneira de separar objetos é por "tipos de valor" que são como primitivos - ints, bools, etc e "tipos de referência" - aulas etc.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top