Escolhendo entre classe e estrutura

Nota

Este conteúdo é reimpresso com permissão da Pearson Education, Inc., a partir de Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries, 2nd Edition. Essa edição foi publicada em 2008 e, desde então, o livro foi totalmente revisto na terceira edição. Algumas das informações nesta página podem estar desatualizadas.

Uma das decisões básicas de design que todo designer de estrutura enfrenta é projetar um tipo como uma classe (um tipo de referência) ou como uma struct (um tipo de valor). Uma boa compreensão das diferenças no comportamento dos tipos de referência e tipos de valor é crucial para fazer esta escolha.

A primeira diferença entre os tipos de referência e os tipos de valor que vamos considerar é que os tipos de referência são alocados na pilha e no lixo coletado, enquanto os tipos de valor são alocados na pilha ou em linha em tipos de contenção e desalocados quando a pilha se desenrola ou quando seu tipo de contenção é deslocalizado. Portanto, alocações e deallocations de tipos de valor são, em geral, mais baratas do que alocações e deallocations de tipos de referência.

Em seguida, matrizes de tipos de referência são alocadas fora de linha, o que significa que os elementos da matriz são apenas referências a instâncias do tipo de referência que residem na pilha. As matrizes de tipo de valor são alocadas em linha, o que significa que os elementos da matriz são as instâncias reais do tipo de valor. Portanto, alocações e deallocations de matrizes de tipo de valor são muito mais baratas do que alocações e deallocations de matrizes de tipo de referência. Além disso, na maioria dos casos, as matrizes de tipo de valor exibem uma localidade de referência muito melhor.

A próxima diferença está relacionada ao uso da memória. Os tipos de valor são encaixotados quando convertidos para um tipo de referência ou uma das interfaces que implementam. Eles são desencaixotados quando lançados de volta para o tipo de valor. Como as caixas são objetos alocados na pilha e são coletados por lixo, muito encaixotamento e desencaixotamento pode ter um impacto negativo na pilha, no coletor de lixo e, finalmente, no desempenho do aplicativo. Em contraste, esse boxe não ocorre quando os tipos de referência são lançados. (Para obter mais informações, consulte Boxe e Unboxing).

Em seguida, as atribuições de tipo de referência copiam a referência, enquanto as atribuições de tipo de valor copiam o valor inteiro. Portanto, atribuições de grandes tipos de referência são mais baratas do que atribuições de grandes tipos de valor.

Finalmente, os tipos de referência são passados por referência, enquanto os tipos de valor são passados por valor. As alterações em uma instância de um tipo de referência afetam todas as referências que apontam para a instância. As instâncias de tipo de valor são copiadas quando são passadas por valor. Quando uma instância de um tipo de valor é alterada, é claro que isso não afeta nenhuma de suas cópias. Como as cópias não são criadas explicitamente pelo usuário, mas são criadas implicitamente quando argumentos são passados ou valores de retorno são retornados, os tipos de valor que podem ser alterados podem ser confusos para muitos usuários. Portanto, os tipos de valor devem ser imutáveis.

Como regra geral, a maioria dos tipos em uma estrutura deve ser classes. Existem, no entanto, algumas situações em que as características de um tipo de valor tornam mais apropriado o uso de structs.

✔️ CONSIDERE definir uma struct em vez de uma classe se instâncias do tipo forem pequenas e geralmente de curta duração ou forem comumente incorporadas em outros objetos.

❌ EVITE definir uma estrutura, a menos que o tipo tenha todas as seguintes características:

  • Representa logicamente um único valor, semelhante aos tipos primitivos (int, double, etc.).

  • Ele tem um tamanho de instância inferior a 16 bytes.

  • É imutável.

  • Não terá de ser encaixotado com frequência.

Em todos os outros casos, você deve definir seus tipos como classes.

© Partes 2005, 2009 Microsoft Corporation. Todos os direitos reservados.

Reimpresso com permissão da Pearson Education, Inc., de Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries, 2nd Edition por Krzysztof Cwalina e Brad Abrams, publicado em 22 de outubro de 2008 por Addison-Wesley Professional como parte da Microsoft Windows Development Series.

Consulte também