O MSDN diz que você deve usar estruturas quando precisar de objetos leves. Existem outros cenários em que uma estrutura é preferível a uma classe?
Algumas pessoas podem ter esquecido que:
- estruturas podem ter métodos.
- estruturas não podem ser herdadas.
Eu entendo as diferenças técnicas entre estruturas e classes, apenas não tenho uma boa ideia de quando usar uma estrutura.
Respostas:
O MSDN tem a resposta: Escolhendo entre classes e estruturas .
Basicamente, essa página fornece uma lista de verificação de 4 itens e diz para usar uma classe, a menos que seu tipo atenda a todos os critérios.
fonte
ref
parâmetros sempre que for razoável. Passar uma estrutura com 4.000 campos como parâmetro ref para um método que altera um será mais barato do que passar uma estrutura com 4 campos por valor para um método que retorna a versão modificada.Estou surpreso por não ter lido nenhuma das respostas anteriores, que considero o aspecto mais crucial:
Eu uso estruturas quando quero um tipo sem identidade. Por exemplo, um ponto 3D:
Se você tem duas instâncias dessa estrutura, não se importa se elas são uma única peça de dados na memória ou duas. Você apenas se preocupa com os valores que eles possuem.
fonte
return false
é o que deveria estar lá, corrigindo agora.Bill Wagner tem um capítulo sobre isso em seu livro "c # eficaz" ( http://www.amazon.com/Effective-Specific-Ways-Improve-Your/dp/0321245660 ). Ele conclui usando o seguinte princípio:
fonte
Use uma estrutura quando desejar a semântica do tipo valor em vez do tipo de referência. As estruturas são copiadas por valor, portanto, tenha cuidado!
Veja também perguntas anteriores, por exemplo
Qual a diferença entre struct e classe no .NET?
fonte
Eu usaria structs quando:
um objeto deve ser somente leitura (toda vez que você passa / atribui uma estrutura, ele é copiado). Objetos somente leitura são ótimos quando se trata de processamento multithread, pois na maioria dos casos não exigem bloqueio.
um objeto é pequeno e tem vida curta. Nesse caso, há uma boa chance de o objeto ser alocado na pilha, o que é muito mais eficiente do que colocá-lo no heap gerenciado. Além disso, a memória alocada pelo objeto será liberada assim que sair do seu escopo. Em outras palavras, é menos trabalhoso para o Garbage Collector e a memória é usada com mais eficiência.
fonte
Use uma classe se:
Use uma estrutura se:
fonte
Eu sempre usei um struct quando desejava agrupar alguns valores para retornar as coisas de uma chamada de método, mas não precisarei usá-lo para nada depois de ler esses valores. Apenas como uma maneira de manter as coisas limpas. Costumo ver as coisas em uma estrutura como "descartáveis" e as coisas em uma classe como mais úteis e "funcionais"
fonte
Se uma entidade for imutável, a questão de usar uma estrutura ou uma classe geralmente será de desempenho, e não de semântica. Em um sistema de 32/64 bits, as referências de classe requerem armazenamento de 4/8 bytes, independentemente da quantidade de informações na classe; copiar uma referência de classe exigirá a cópia de 4/8 bytes. Por outro lado, todos os distintosA instância de classe terá 8/16 bytes de sobrecarga, além das informações que ela contém e do custo de memória das referências a ela. Suponha que se queira uma matriz de 500 entidades, cada uma contendo quatro números inteiros de 32 bits. Se a entidade for um tipo de estrutura, a matriz exigirá 8.000 bytes, independentemente de todas as 500 entidades serem todas idênticas, diferentes ou em algum lugar intermediário. Se a entidade for do tipo classe, a matriz de 500 referências ocupará 4.000 bytes. Se todas essas referências apontarem para objetos diferentes, os objetos exigiriam 24 bytes adicionais cada (12.000 bytes para todos os 500), um total de 16.000 bytes - o dobro do custo de armazenamento de um tipo de estrutura. Por outro lado, do código criou uma instância de objeto e copiou uma referência para todos os 500 slots da matriz, o custo total seria de 24 bytes para essa instância e 4, 000 para a matriz - um total de 4.024 bytes. Uma grande economia. Poucas situações funcionariam tão bem quanto a última, mas, em alguns casos, pode ser possível copiar algumas referências para slots de matriz suficientes para que esse compartilhamento valha a pena.
Se a entidade deve ser mutável, a questão de usar uma classe ou estrutura é, de certa forma, mais fácil. Suponha que "Thing" seja uma estrutura ou classe que possua um campo inteiro chamado xe faça o seguinte código:
Alguém quer que a última declaração afete t1.x?
Se Thing for um tipo de classe, t1 e t2 serão equivalentes, ou seja, t1.x e t2.x também serão equivalentes. Portanto, a segunda instrução afetará t1.x. Se Thing for um tipo de estrutura, t1 e t2 serão instâncias diferentes, significando que t1.xe t2.x se referirão a números inteiros diferentes. Portanto, a segunda instrução não afetará t1.x.
Estruturas mutáveis e classes mutáveis têm comportamentos fundamentalmente diferentes, embora o .net tenha algumas peculiaridades no tratamento de mutações struct. Se alguém quiser um comportamento de tipo de valor (o que significa que "t2 = t1" copiará os dados de t1 para t2, deixando t1 e t2 como instâncias distintas) e se puder conviver com as peculiaridades no manuseio de tipos de valores pela .net, use uma estrutura. Se alguém quiser semântica de tipo de valor, mas as peculiaridades de .net causariam uma semântica de tipo de valor quebrada no aplicativo, use uma classe e murmure.
fonte
Além disso, as excelentes respostas acima:
Estruturas são tipos de valor.
Eles nunca podem ser definidos como Nothing .
Definir uma estrutura = Nothing, definirá todos os seus tipos de valores para seus valores padrão.
fonte
quando você realmente não precisa de comportamento, mas precisa de mais estrutura do que uma simples matriz ou dicionário.
Acompanhamento É assim que penso nas estruturas em geral. Eu sei que eles podem ter métodos, mas eu gosto de manter essa distinção mental geral.
fonte
Como o @Simon disse, as estruturas fornecem semântica "do tipo valor"; portanto, se você precisar de um comportamento semelhante ao tipo de dados interno, use uma struct. Como as estruturas são passadas por cópia, você deseja garantir que elas sejam pequenas em tamanho, cerca de 16 bytes.
fonte
É um tópico antigo, mas queria fornecer um teste de benchmark simples.
Eu criei dois arquivos .cs:
e
Executar referência:
Resultados:
fonte
Hmm...
Eu não usaria a coleta de lixo como argumento a favor / contra o uso de estruturas versus classes. O heap gerenciado funciona como uma pilha - criar um objeto apenas o coloca no topo do heap, quase tão rápido quanto a alocação na pilha. Além disso, se um objeto tem vida curta e não sobrevive a um ciclo de GC, a desalocação é gratuita, pois o GC funciona apenas com memória ainda acessível. (Pesquise no MSDN, há uma série de artigos sobre gerenciamento de memória .NET. Estou com preguiça de procurar por eles).
Na maioria das vezes eu uso uma estrutura, acabo me chutando por fazer isso, porque depois descobri que ter semântica de referência tornaria as coisas um pouco mais simples.
De qualquer forma, esses quatro pontos no artigo do MSDN postados acima parecem uma boa diretriz.
fonte
class MutableHolder<T> { public T Value; MutableHolder(T value) {Value = value;} }
e aMutableHolder<T>
será um objeto com semântica de classe mutável (isso funciona da mesma forma seT
for uma estrutura ou um tipo de classe imutável).As estruturas estão na pilha e não no heap; portanto, são seguras para encadeamento e devem ser usadas ao implementar o padrão de objeto de transferência; você nunca deseja usar objetos no heap, eles são voláteis; nesse caso, você deseja usar a pilha de chamadas, este é um caso básico para usar uma estrutura. Estou surpreso com todas as respostas aqui,
fonte
Eu acho que a melhor resposta é simplesmente usar struct quando o que você precisa é uma coleção de propriedades, classe quando é uma coleção de propriedades E comportamentos.
fonte