Pergunta

Procuro uma resposta clara, concisa e precisa.

Idealmente, como a resposta real, embora sejam bem-vindos links para boas explicações.

Foi útil?

Solução

Os valores em caixa são estruturas de dados que são invólucros mínimos ao redor tipos primitivos*.Valores em caixa são normalmente armazenados como ponteiros para objetos em a pilha.

Assim, os valores em caixa usam mais memória e exigem no mínimo duas pesquisas de memória para serem acessados:uma vez para obter o ponteiro e outra para seguir esse ponteiro até o primitivo.Obviamente, esse não é o tipo de coisa que você deseja em seus loops internos.Por outro lado, os valores em caixa normalmente funcionam melhor com outros tipos no sistema.Por serem estruturas de dados de primeira classe na linguagem, elas possuem os metadados e a estrutura esperados que outras estruturas de dados possuem.

Em 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 do Java são usados ​​apenas para verificação de tipo em tempo de compilação, o .NET irá gerar classes específicas para cada tipo genérico instanciado em tempo de execução.

Java e Haskell possuem arrays unboxed, mas são claramente menos convenientes que as outras coleções.No entanto, quando o desempenho máximo é necessário, vale a pena um pouco de inconveniência para evitar a sobrecarga de encaixotar e desembalar.

* Para esta discussão, um valor primitivo é qualquer um que possa ser armazenado em a pilha de chamadas, em vez de armazenado como um ponteiro para um valor no heap.Freqüentemente, são apenas os tipos de máquina (ints, floats, etc.), estruturas e, às vezes, matrizes de tamanho estático.O .NET-land os chama de tipos de valor (em oposição a tipos de referência).O pessoal de Java os chama de tipos primitivos.Haskellions apenas os chamam de desembalados.

** 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 abordagem “Tudo é um objeto”***.

*** Embargo:Um compilador/JIT suficientemente avançado pode, em alguns casos, realmente detectar que um valor que é semanticamente encaixotado ao olhar para a fonte pode ser com segurança um valor não encaixotado em tempo de execução.Em essência, graças a implementadores de linguagem brilhantes, suas caixas às vezes são gratuitas.

Outras dicas

de C# 3.0 em poucas palavras:

Boxe é o ato de lançar um valor digite em um tipo de referência:

int x = 9; 
object o = x; // boxing the int

desembalar é...o reverso:

// unboxing o
object o = 9; 
int x = (int)o; 

Boxing e unboxing é o processo de conversão de um valor primitivo em uma classe wrapper orientada a objetos (boxing) ou de conversão de um valor de uma classe wrapper orientada a objetos de volta ao valor primitivo (unboxing).

Por exemplo, em java, pode ser necessário converter um int valor em um Integer (caixa) se você quiser armazená-lo em um Collection porque primitivas não podem ser armazenadas em um Collection, apenas objetos.Mas quando você quiser recuperá-lo do Collection você pode querer obter o valor como um int e não um Integer então você iria desempacotá-lo.

Encaixotar e desembalar não é inerentemente ruim, mas é uma troca.Dependendo da implementação da linguagem, pode ser mais lento e consumir mais memória do que apenas usar primitivos.No entanto, também pode permitir que você use estruturas de dados de nível superior e obtenha maior flexibilidade em seu código.

Hoje em dia, é mais comumente discutido no contexto do recurso "autoboxing/autounboxing" do Java (e de outras linguagens).Aqui está um explicação centrada em java do autoboxing.

Na rede:

Muitas vezes você não pode confiar no tipo de variável que uma função consumirá, então você precisa usar uma variável de objeto que se estenda do menor denominador comum - em .Net isso é object.

No entanto object é uma classe e armazena seu conteúdo como referência.

List<int> notBoxed = new List<int> { 1, 2, 3 };
int i = notBoxed[1]; // this is the actual value

List<object> boxed = new List<object> { 1, 2, 3 };
int j = (int) boxed[1]; // this is an object that can be 'unboxed' to an int

Embora ambos contenham as mesmas informações, a segunda lista é maior e mais lenta.Cada valor na segunda lista é na verdade uma referência a um object que detém o int.

Isso é chamado de caixa porque o int está envolto pelo object.Quando é lançado de volta o int está fora da caixa - convertido de volta ao seu valor.

Para tipos de valor (ou seja,todos structs) isso é lento e potencialmente usa muito mais espaço.

Para tipos de referência (ou seja,todos classes) isso é um problema muito menor, 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 então você está comparando valores, mas quando você compara dois classes então (por padrão) você está comparando a referência - ou seja,são a mesma instância?

Isso pode ser confuso ao lidar com tipos de valores em caixa:

int a = 7;
int b = 7;

if(a == b) // Evaluates to true, because a and b have the same value

object c = (object) 7;
object d = (object) 7;

if(c == d) // Evaluates to false, because c and d are different instances

É fácil contornar:

if(c.Equals(d)) // Evaluates to true because it calls the underlying int's equals

if(((int) c) == ((int) d)) // Evaluates to true once the values are cast

No entanto, é outra coisa a ter cuidado ao lidar com valores em caixa.

As coleções genéricas do .NET FCL:

List<T>
Dictionary<TKey, UValue>
SortedDictionary<TKey, UValue>
Stack<T>
Queue<T>
LinkedList<T>

foram todos projetados para superar os problemas de desempenho de boxing e unboxing em implementações de coleção anteriores.

Para mais informações, consulte o capítulo 16, CLR via C# (2ª edição).

Boxe é o processo de conversão de um tipo de valor em um tipo de referência.

Unboxing é a conversão de um tipo de referência em um tipo de valor.

EX: int i=123;
    object o=i;// Boxing
    int j=(int)o;// UnBoxing

Os tipos de valor são:
int, char e estruturas, enumerações.Os tipos de referência são:Classes, interfaces, arrays, strings e objetos

Boxing e unboxing facilitam que tipos de valor sejam tratados como objetos.Boxe significa converter um valor em uma instância do tipo de referência de objeto.Por exemplo, Int é uma aula e int é um tipo de dados.Convertendo int para Int é uma exemplificação do boxe, enquanto a conversão Int para int está desempacotando.O conceito auxilia na coleta de lixo, o Unboxing, por outro lado, converte o tipo de objeto em tipo de valor.

int i=123;
object o=(object)i; //Boxing

o=123;
i=(int)o; //Unboxing.

Como qualquer outra coisa, o autoboxing pode ser problemático se não for usado com cuidado.O clássico é acabar com uma NullPointerException e não conseguir rastreá-la.Mesmo com um depurador.Experimente isto:

public class TestAutoboxNPE
{
    public static void main(String[] args)
    {
        Integer i = null;

        // .. do some other stuff and forget to initialise i

        i = addOne(i);           // Whoa! NPE!
    }

    public static int addOne(int i)
    {
        return i + 1;
    }
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top