Estou procurando uma resposta clara, concisa e precisa.
Idealmente, como a resposta real, embora os links para boas explicações sejam bem-vindos.
Estou procurando uma resposta clara, concisa e precisa.
Idealmente, como a resposta real, embora os links para boas explicações sejam bem-vindos.
language-but-not-type-agnostic
.static-language-agnostic
? Não tenho certeza de que o SO precise da distinção; pode ser uma boa pergunta para a meta.Respostas:
Valores em caixa são estruturas de dados que são invólucros mínimos em torno de tipos primitivos *. Os valores em caixa geralmente são armazenados como ponteiros para objetos na pilha .
Assim, os valores em caixa usam mais memória e levam no mínimo duas pesquisas de memória para acessar: uma para obter o ponteiro e outra para segui-lo até o primitivo. Obviamente, este não é o tipo de coisa que você deseja em seus circuitos internos. Por outro lado, os valores em caixa normalmente são melhores com outros tipos no sistema. Como são estruturas de dados de primeira classe no idioma, eles têm os metadados e a estrutura esperados que outras estruturas de dados possuem.
No Java e Haskell, as coleções genéricas não podem conter valores sem caixa. Coleções genéricas no .NET podem conter valores sem caixa, sem penalidades. Onde os genéricos de Java são usados apenas para verificação de tipo em tempo de compilação, o .NET gera classes específicas para cada tipo genérico instanciado em tempo de execução .
Java e Haskell têm matrizes sem caixa, mas são claramente menos convenientes do que as outras coleções. No entanto, quando o desempenho máximo é necessário, vale a pena um pequeno inconveniente para evitar a sobrecarga do boxe e do unboxing.
* Para esta discussão, um valor primitivo é aquele que pode ser armazenado na pilha de chamadas , em vez de ser armazenado como um ponteiro para um valor no heap. Freqüentemente, são apenas os tipos de máquinas (entradas, flutuadores, etc.), estruturas e, às vezes, matrizes de tamanho estático. O .NET-land os chama de tipos de valor (em oposição aos tipos de referência). O pessoal de Java os chama de tipos primitivos. Os haskellions apenas os chamam de fora da caixa.
** Também estou focando em Java, Haskell e C # nesta resposta, porque é isso que eu sei. Pelo que vale, Python, Ruby e Javascript têm valores exclusivamente em caixa. Isso também é conhecido como a abordagem "Tudo é um objeto" ***.
*** Advertência: Em alguns casos, um compilador / JIT suficientemente avançado pode realmente detectar que um valor que é semanticamente encaixotado ao olhar a fonte pode ser com segurança um valor não encaixotado no tempo de execução. Em essência, graças aos implementadores de linguagem brilhantes, suas caixas às vezes são gratuitas.
fonte
do C # 3.0 Em poucas palavras :
fonte
Boxing & unboxing é o processo de converter um valor primitivo em uma classe de wrapper orientada a objetos (boxing) ou converter um valor de uma classe de wrapper orientada a objetos de volta ao valor primitivo (unboxing).
Por exemplo, em java, pode ser necessário converter um
int
valor em umInteger
(boxe) se você deseja armazená-lo em,Collection
porque os primitivos não podem ser armazenados emCollection
apenas objetos. Mas quando você deseja recuperá-lo,Collection
você pode obter o valor como umint
e não um,Integer
para que você o desmarque.Boxe e unboxing não são inerentemente ruins , mas são uma troca. Dependendo da implementação do idioma, ele pode ser mais lento e consome mais memória do que apenas o uso de primitivas. No entanto, também pode permitir que você use estruturas de dados de nível superior e obtenha maior flexibilidade no seu código.
Atualmente, é mais discutido no contexto do recurso "autoboxing / autounboxing" de Java (e de outra linguagem). Aqui está uma explicação centrada em java do autoboxing .
fonte
Na rede:
Freqüentemente, você não pode confiar no tipo de variável que uma função consumirá; portanto, é necessário usar uma variável de objeto que se estende do menor denominador comum - em .Net, este é
object
.No entanto,
object
é uma classe e armazena seu conteúdo como referência.Enquanto ambos mantêm a mesma informação, a segunda lista é maior e mais lenta. Cada valor na segunda lista é na verdade uma referência a um
object
que contém oint
.Isso é chamado de caixa porque o
int
é envolvido peloobject
. Quando ele é lançado fora daint
caixa - convertido de volta ao seu valor.Para tipos de valor (isto é, todos
structs
), isso é lento e potencialmente usa muito mais espaço.Para tipos de referência (isto é, todos
classes
), isso é muito menos problemático, pois eles são armazenados como referência de qualquer maneira.Um outro problema com um tipo de valor em caixa é que não é óbvio que você está lidando com a caixa, e não com o valor. Quando você compara dois
structs
, você está comparando valores, mas quando você compara dois,classes
então (por padrão), você está comparando a referência - ou seja, essas são a mesma instância?Isso pode ser confuso ao lidar com tipos de valor em caixa:
É fácil contornar:
No entanto, é outra coisa a ter cuidado ao lidar com valores em caixa.
fonte
Object
não implementa o operador de igualdade, mas os tipos de classe podem ser comparados com oIs
operador; por outro lado,Int32
pode ser usado com o operador de igualdade, mas nãoIs
. Essa distinção torna muito mais claro que tipo de comparação está sendo feita.Boxing
é o processo de conversão de um tipo de valor em um tipo de referência. Considerando queUnboxing
é a conversão de um tipo de referência em um tipo de valor.Tipos de valor são:
int
,char
estructures
,enumerations
. Tipos de referência são:Classes
,interfaces
,arrays
,strings
eobjects
fonte
As coleções genéricas do FCL do .NET:
foram todos projetados para superar os problemas de desempenho do boxe e do unboxing nas implementações de coleções anteriores.
Para obter mais informações, consulte o capítulo 16, CLR via C # (2ª edição) .
fonte
O boxe e o unboxing facilitam os tipos de valor a serem tratados como objetos. Boxe significa converter um valor em uma instância do tipo de referência do objeto. Por exemplo,
Int
é uma classe eint
é um tipo de dados. A conversãoint
paraInt
é uma exemplificação do boxe, enquanto a conversãoInt
paraint
é unboxing. O conceito ajuda na coleta de lixo, o Unboxing, por outro lado, converte o tipo de objeto em tipo de valor.fonte
var ii = 123; typeof ii
retornanumber
.var iiObj = new Number(123); typeof iiObj
retornaobject
.typeof ii + iiObj
retornanumber
. Portanto, este é o equivalente javascript do boxe. O valor iiObj foi automaticamente convertido em um número primitivo (sem caixa) para executar a aritmética e retornar um valor sem caixa.Como qualquer outra coisa, a autoboxing pode ser problemática se não for usada com cuidado. O clássico é acabar com uma NullPointerException e não conseguir rastreá-la. Mesmo com um depurador. Tente o seguinte:
fonte
i
é inicializada prematuramente. Faça uma declaração vazia (Integer i;
) para que o compilador possa indicar que você esqueceu de inicializá-lo ou aguarde para declará-lo até conhecer seu valor.