Pergunta

Duplicate possíveis:
Porque são estruturas mutáveis ??mal?

Eu li em muitos lugares incluindo aqui que é melhor para fazer estruturas como imutável.

Qual é a razão por trás disso? Vejo muitas estruturas Microsoft-criados que são mutáveis, como os de XNA. Provavelmente há muitos mais na BCL.

Quais são os prós e contras de não seguir essa diretriz?

Foi útil?

Solução

Structs deve representar valores . Valores não mudam. O número 12 é eterna.

No entanto, considere:

Foo foo = new Foo(); // a mutable struct
foo.Bar = 27;
Foo foo2 = foo;
foo2.Bar = 55;

Agora foo.Bar e foo2.Bar é diferente, o que é muitas vezes inesperada. Especialmente nos cenários como propriedades (felizmente o compilador detectar isso). Mas também coleções etc; como você nunca transformar-los de forma sensata?

A perda de dados é muito fácil com estruturas mutáveis.

Outras dicas

A grande con é que as coisas não se comportam como você espera que eles -. Particularmente se a mutabilidade vem de uma mistura do valor direto e um tipo de referência dentro dele

Para ser honesto, eu não me lembro fora do topo da minha cabeça todos os problemas estranhos que já vi as pessoas vêm com em newsgroups quando eles usaram estruturas mutáveis ??-, mas certamente existem essas razões. mutáveis ??estruturas causam problemas. Fique longe.

EDIT: Acabei de encontrar um e-mail que eu escrevi há um tempo atrás sobre este tema. Elabora-se um pouco:

  • É filosoficamente errado: a struct deve representar algum tipo de valor fundamental. Essas são basicamente imutável. Você não consegue mudar o número 5. É possível alterar o valor de uma variável 5-6, mas você não logicamente fazer uma mudança para o próprio valor.

  • É praticamente um problema: ele cria muitas situações estranhas. É particularmente ruim se é mutável através de uma interface. Então você pode começar a mudar os valores em caixa. Ick. Eu vi um monte de mensagens de grupos de notícias que são devidos a pessoas que tentam usar estruturas mutáveis ??e correndo em problemas. Eu vi um exemplo LINQ muito estranho que estava falhando porque List<T>.Enumerator é um struct, por exemplo.

Eu uso estruturas mutáveis, muitas vezes no meu projeto (desempenho crítico) - e eu não correr em problemas, porque eu entendo as implicações da cópia semântica. Tanto quanto eu posso dizer, a principal razão as pessoas defendem estruturas imutáveis ??é para que as pessoas que não compreender as implicações não pode obter-se em apuros.

Isso não é uma coisa tão terrível - mas estamos em perigo agora de se tornar "a verdade do evangelho", quando na verdade há momentos em que é legitimamente a melhor opção para fazer um mutável struct. Como com todas as coisas, há exceções à regra.

Não há nada mais barato para manipular do que um struct mutável, é por isso que muitas vezes você vê-lo no código de alto desempenho, como os de processamento gráfico rotinas.

Infelizmente estruturas mutáveis ??não joga bem com objetos e propriedades, é muito fácil de modificar uma cópia de um stuct em vez da própria estrutura. Assim, eles não são adequados para a maioria de seu código.

P.S. Para evitar o custo de copiar estruturas mutáveis, eles são normalmente armazenados e passou em arrays.

A razão técnica é que estruturas mutáveis ?? aparecer para ser capaz de fazer coisas que eles realmente não fazer. Desde a semântica de tempo de design são os mesmos tipos de referência, este torna-se confuso para os desenvolvedores. Este código:

public void DoSomething(MySomething something)
{
    something.Property = 10;
}

comporta-se de forma bastante diferente, dependendo se MySomething é um struct ou um class. Para mim, esta é uma obrigação, mas não a razão mais atraente. Se você olhar para DDD 's Valor objeto , você pode ver a conexão à forma como estruturas devem ser tratados. Um objecto de valor em DDD pode ser melhor representada como um tipo de valor em Net (e, por conseguinte, uma estrutura). Porque ele não tem identidade, não pode mudar.

Pense nisso em termos de algo como seu endereço. Você pode "mudar" o seu endereço, mas o próprio endereço não mudou. Na verdade, você tem um novo endereço atribuído a você. Conceitualmente, isso funciona, porque se você realmente mudado seu endereço, seus companheiros de quarto teria de mudar também.

Você pediu para os prós e contras de não seguindo a orientação que estruturas devem ser imutáveis.

Contras:. Os contras são bem coberto de respostas existentes, ea maioria dos problemas descritos são devido à mesma causa - um comportamento inesperado devido à semântica de valor structs

Pros: O principal pro do uso estruturas mutáveis ??pode ser desempenho . Obviamente, este conselho vem com todas as advertências habituais sobre otimizações:. Certifique-se de que a parte do seu código necessidades a serem otimizados e certifique-se de todas as mudanças que realmente otimizar o desempenho do seu código através de perfis

Para um excelente artigo que discute quando você pode querer usar estruturas mutáveis, ver de Rico Mariani Teste de Desempenho em Programação Value-Based (ou mais especificamente, as respostas ).

A estrutura geralmente deve representar uma única unidade de algum tipo. Como tal, não faz muito sentido para alterar uma das propriedades do valor, faz mais sentido criar um completamente novo valor se você quiser um valor que é diferente de alguma forma.

A semântica fica mais simples quando se utiliza estruturas imutáveis, e você evitar armadilhas como este:

// a struct
struct Interval {
   int From { get; set; }
   int To { get; set; }
}

// create a list of structs
List<Interval> intervals = new List<Interval>();

// add a struct to the list
intervals.Add(new Interval());

// try to set the values of the struct
intervals[0].From = 10;
intervals[0].To = 20;

O resultado é que a estrutura na lista não é alterado em tudo. A expressão intervalo [0] copia o valor da estrutura da lista, em seguida, alterar a propriedade do valor temporário, mas o valor nunca é colocado de volta na lista.

Edit:. Mudou o exemplo de usar uma lista em vez de um array

Quando você copia estruturas em torno de você copiar seu conteúdo, por isso, se você modificar uma versão copiada do "original" não será atualizado.

Esta é uma fonte de erros, uma vez que mesmo se você sabe que você cair na armadilha de copiar um struct (apenas passando-a para um método) e modificar a cópia.

Apenas aconteceu comigo novamente na semana passada, me manteve uma busca hora para um bug.

Manter estruturas imutáveis ??impede que ...

Diferente do que você precisa ter certeza de que você tem uma boa razão para usar estruturas em primeiro lugar - "otimização" ou "Eu quero algo que aloca rapidamente na pilha" não conta como uma resposta. Empacotamento ou coisas onde dependem de layout -. Ok, mas você não deve normalmente guardam as estruturas ao redor por muito tempo, eles são valores não objetos

a razão que você deve fazer estruturas imutável é que eles são valuetypes , o que significa que eles são copiados cada vez que você passá-las para um método.

Assim, se, por exemplo, você tinha uma propriedade que retornou um struct, modificando o valor de um campo em que a estrutura seria inútil, porque o getter retornaria um cópia da estrutura, em vez do que uma referência para a estrutura. Eu já vi isso em código, e é muitas vezes difícil de pegar.

Se você projetar suas estruturas de imutabilidade, você ajuda o programador evitar esses erros.

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