Pregunta

Estoy trabajando en crear una clase inmutable.
He marcado todas las propiedades como de solo lectura.

Tengo una lista de elementos en la clase.
Aunque si la propiedad es de solo lectura, la lista puede modificarse.

Exponer el IEnumerable de la lista lo hace inmutable.
¿Quería saber cuáles son las reglas básicas que hay que seguir para hacer que una clase sea inmutable?

¿Fue útil?

Solución

Creo que estás en el camino correcto -

  • toda la información inyectada en la clase debe proporcionarse en el constructor
  • todas las propiedades deben ser solo getters
  • si una colección (o matriz) se pasa al constructor, debe copiarse para evitar que la persona que llama la modifique más tarde
  • si va a devolver su colección, devuelva una copia o una versión de solo lectura (por ejemplo, usando ArrayList.ReadOnly o similar: puede combinar esto con el punto anterior y almacenar una copia de solo lectura para devolver cuando las personas que llaman accedan a él), devuelva un enumerador o use algún otro método / propiedad que permita el acceso de solo lectura a la colección
  • tenga en cuenta que aún puede tener la apariencia de una clase mutable si alguno de sus miembros es mutable; si este es el caso, debe copiar cualquier estado que desee retener y evitar devolver objetos mutables completos, a menos que los copia antes de devolverlos a la persona que llama; otra opción es devolver solo " secciones " del objeto mutable - gracias a @Brian Rasmussen por animarme a expandir este punto

Otros consejos

Para ser inmutable, todas sus propiedades y campos deben ser de solo lectura. Y los elementos en cualquier lista deberían ser inmutables.

Puede hacer una propiedad de lista de solo lectura de la siguiente manera:

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

}

Además, tenga en cuenta que:

public readonly object[] MyObjects;

no es inmutable incluso si está marcado con una palabra clave de solo lectura. Todavía puede cambiar las referencias / valores individuales de la matriz por el índice de acceso.

Use la clase ReadOnlyCollection. Está situado en el System.Collections.ObjectModel espacio de nombres.

En cualquier cosa que devuelva su lista (o en el constructor), configure la lista como una colección de solo lectura.

using System.Collections.ObjectModel;

...

public MyClass(..., List<ListItemType> theList, ...)
{
    ...
    this.myListItemCollection= theList.AsReadOnly();
    ...
}

public ReadOnlyCollection<ListItemType> ListItems
{
     get { return this.myListItemCollection; }
}

Otra opción sería usar un patrón de visitante en lugar de exponer cualquier colección interna.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top