Como faço para criar uma classe imutável?
-
20-08-2019 - |
Pergunta
Eu estou trabalhando na criação de uma classe imutável.
Eu marquei todas as propriedades como somente leitura.
Eu tenho uma lista de itens na classe.
Embora se a propriedade é somente leitura da lista pode ser modificada.
A exposição do IEnumerable da lista torna imutável.
Eu queria saber o que são as regras básicas um tem que seguir para fazer uma imutável classe?
Solução
Eu acho que você está no caminho certo -
- todas as informações injetado na classe deve ser fornecido no construtor
- todas as propriedades devem ser getters única
- Se uma coleção (ou Array) é passado para o construtor, ele deve ser copiado para manter o chamador de modificá-lo mais tarde
- se você estiver indo para retornar a sua colecção, ou retornar uma cópia ou uma versão apenas de leitura (por exemplo, usando ArrayList.ReadOnly ou similar - você pode combinar isso com o ponto anterior e loja um read-only copiar a ser devolvido quando os chamadores acessá-lo), retornar um recenseador, ou usar algum outro método / propriedade que permite acesso somente leitura para a coleção
- manter em mente que você ainda pode ter a aparência de uma classe mutável, se qualquer um dos seus membros são mutáveis ??- se este for o caso, você deve copiar afastado qualquer estado que você vai querer reter e evitar o retorno objetos mutáveis ??inteiros, a menos copiá-los antes de dar-los de volta para o chamador - outra opção é retornar apenas "seções" imutáveis ??do objeto mutável - graças a @ Brian Rasmussen por me encorajar a expandir este ponto
Outras dicas
Para ser imutável, todas as suas propriedades e campos deve ser somente leitura. E os itens em qualquer lista de si mesmos devem ser imutáveis.
Você pode fazer uma propriedade de lista somente leitura da seguinte forma:
public class MyClass
{
public MyClass(..., IList<MyType> items)
{
...
_myReadOnlyList = new List<MyType>(items).AsReadOnly();
}
public IList<MyType> MyReadOnlyList
{
get { return _myReadOnlyList; }
}
private IList<MyType> _myReadOnlyList
}
Além disso, mantenha em mente que:
public readonly object[] MyObjects;
não é imutável mesmo que seja marcada com palavra-chave readonly. Você ainda pode alterar as referências de matriz / valores individuais por índice acessor.
Use a classe ReadOnlyCollection
. Ele está situado no espaço de nomes System.Collections.ObjectModel
.
Em qualquer coisa que retorna a sua lista (ou no construtor), defina a lista como uma coleção somente leitura.
using System.Collections.ObjectModel;
...
public MyClass(..., List<ListItemType> theList, ...)
{
...
this.myListItemCollection= theList.AsReadOnly();
...
}
public ReadOnlyCollection<ListItemType> ListItems
{
get { return this.myListItemCollection; }
}
Outra opção seria a utilização de um padrão do visitante em vez de expor quaisquer coleções internas em tudo.