Pergunta

Eu sei que o boxe é um conceito popular com abundância de informações disponíveis sobre isso, mas eu tenho algumas perguntas que eu realmente não posso encontrar respostas para:

1) Se as linhas de boxe para um tipo de valor (struct) que está sendo convertido em um objeto (tipo de referência), ou tipo de referência, então por que usar um tipo de valor que será embalado e incorrer em uma penalidade de desempenho? Estou ciente dos benefícios e adequação em determinados casos de qualquer um struct ou classe. Diz-se (1) que os valores (tipos de valor) tendem a viver na pilha em um espaço de armazenamento temporário, mas por quanto tempo? Se eu não preciso do tipo, como posso garantir que ele é cuidado e eliminados naquele momento? Ou isso é onde o padrão descartável entra em jogo? Presumo que a razão para utilizar um struct será devido aos seus benefícios.

Curiosamente, se eu usar uma estrutura para armazenar duas cordas e um campo DateTime, a estrutura irá realizar duas referências (cordas) e a data e hora juntos. Eu, obviamente, assumir esta é mais rápido do que os valores que estão sendo espalhados. É lá que eu precisar de alguma coisa para estar ciente de neste projeto? (2).

1) http: //en.csharp-online .net / classes, estruturas e objetos-boxing e unboxing

2) http://dotnetperls.com/Content/Struct-Examples.aspx

Eu fiz uma pesquisa sobre aqui para as respostas que eu sou depois, mas sem sorte. Eu costumo fazer pesquisas neste site para temas como GC, os genéricos, tratamento de exceções, etc, pois há muita sabedoria para aprender e compartilhar.

Obrigado por o (potencial) a educação a todos os cartazes! Por favor, desculpe qualquer ingenuidade potencial. Aprender os internos leva-me muito bem para passar algum tempo na compreensão IL, etc (algo para resolver, em breve).

Foi útil?

Solução

Se você nunca passar o tipo de valor em uma variável de referência, em seguida, o boxe não vai ocorrer. Quando você não sabe, em seguida, responder às seguintes perguntas :

  • O ato como tipos primitivos.
  • têm um tamanho instância com menos de 16 bytes.
  • são imutáveis.
  • semântica Valor são desejáveis.

Eu também costumam considerar o que é a vida de tal variável a. Se é uma variável local usado dentro de um método então eu iria tenda para uso struct (caso contrário classe).

Outras dicas

Você deve usar tipos de valor por causa de seu benefício lógico, não os ganhos de desempenho. Dito isto, porque os tipos de valor são geridos na pilha, não precisa participar de coleta de lixo. Se você tem um tipo que está constantemente criados e descartados (como um int, float, double, etc), então você pode obter um bom impulso, transformando-as em estruturas. A única coisa a ter cuidado é que você só deve realmente considerar isso se você também pode fazer a imutável struct.

Um par de outras coisas a considerar -

Em primeiro lugar, você quer certificar-se de estruturas são imutáveis ??(em geral). Devido a isso, é uma boa regra de ouro para não ter estruturas que contêm tipos de referência. Cordas pode ser uma exceção a esta, uma vez que está imutável em C #, mas em termos de uma regra de propósito geral do polegar para o projeto, eu seria cauteloso com isso.

Em segundo lugar, há um outro caso de uso para estruturas que não foi mencionado até agora - um grande número de pequenos objetos. Se você tem uma grande lista ou matriz de pequenos objetos, estruturas fornecem muito melhor coerência de cache e são absolutamente críticos. É por isso que a maioria dos motores 3D usam estruturas para pontos / vetores -. Eles tendem a ter grandes conjuntos de pontos para vértices, etc

Este é algo que vale prestar atenção a se o desempenho é uma parte importante da sua aplicação. Por exemplo, em uma das minhas aplicações, a alteração de um único tipo de uma classe para um struct raspada 40% em uma corrida de longa (> 5 minutos de tempo de execução) processo. Tendo os objetos juntos na memória se você estiver usando-os repetidamente em cálculos matemáticos pesados ??pode fornecer ganhos enormes.

Agora - no seu caso, ter 2 cordas e uma DateTime provavelmente não vai ver qualquer melhoria deste. O tipo de rotinas que iria trabalhar em cordas provavelmente não está fazendo computação pesada (espero), ou seja:. Transformadora a meio milhão de pontos no espaço, ou fazendo uma solução matriz grande, etc

Finalmente - você vai notar que .net3.5sp1 feita estruturas muito mais útil. Antes de 3.5SP1 (em x86), não havia inlining de métodos com chamadas struct. Isso limitou o desempenho ganha possível através de estruturas. Atualizar seu quadro pode tornar o código struct idade muito, muito mais rápido (em certos casos).

Você não precisa sempre de boxe, e com os genéricos não há necessidade para isso.
A memória usada por tipos de valor (struct é um tipo de valor) será reivindicado como
Assim como o método termina / retornos e você não
necessidade de fazer qualquer coisa para que isso aconteça.
tipos de valores declarados como membros de instância será na memória até que o objeto
é eliminada pela GC.
tipos de referência são mantidos no heap gerenciado.
tipos de referência instanciado dentro de um método será excluído pelo
coletor de lixo quando nenhum objeto está mantendo uma referência a ele.

GC funciona por si só e para a maior parte que você deve deixá-lo sozinho.
Você não pode prever quando um objeto vai ser eliminado pelo GC.

O padrão de Descarte é usado em tipos de referência, mas não vai forçar GC excluir
um objeto. É geralmente usado para recursos não gerenciados livres.

Para valores na pilha considerar o seguinte:
Vamos dizer que você tem um programa simples com três métodos, como abaixo:
Quando este programa é executado, o método principal é executado, e assim por diante. Por favor, siga o
números abaixo:


Main
{
   // (0) Stack is empty
   int firstInt = 0;
   // (1) Stack now contains:
   //                     firstInt
   DoSomething1();
   // (7) Stack still contains:
   //                     firstInt
}
// Program ends

DoSomething()
{
   int anInteger = 0; 
   // (2) Stack now contains:
   //                    anInteger
   //                    firstInt
   DoMore()
   // (5) Stack now contains:
   //                     anInteger
   //                     firstInt
}
// (6) anInteger goes out of scope

DoMore
{
  int anotherInteger = 1; 
   // (3) Stack now contains:
   //                     anotherInteger
   //                     anInteger
   //                     firstInt
}
// (4) anotherInteger goes out of scope

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