2010-03-29 23 views

Respuesta

29

Un tipo inmutable es un tipo cuyas propiedades solo se pueden configurar en la inicialización. Una vez que se crea un objeto, ya no se puede cambiar nada. Una propiedad inmutable es simplemente una propiedad de solo lectura. En el siguiente ejemplo, ImmutableType es un tipo inmutable con una propiedad Test. La prueba es una propiedad de solo lectura. Solo se puede configurar en la construcción.

class ImmutableType 
{ 
    private readonly string _test; 
    public string Test 
    { 
     get { return _test; } 
    } 

    public ImmutableType(string test) 
    { 
     _test = test; 
    } 
} 

Ver también: The Wikipedia article y some StackOverflow questions sobre el tema.

+4

Puede imponer la inmutabilidad contra futuros cambios de clase al anteponer _test con readonly. Desafortunadamente, lamentablemente no hay propiedades inmutables auto implementadas en C#. –

+0

@Sam: gracias, actualizó el ejemplo. – fretje

+3

Esto se torna un poco más complicado cuando sus propiedades son tipos de referencia. La definición, entonces, de inmutable se puede interpretar como la * referencia * es inmutable _o_ el * gráfico del objeto * es inmutable (dependiendo de sus necesidades, pero generalmente es el último - vea el artículo de Wiki). –

4

fretje es correcto. El ejemplo más popular de un tipo inmutable es un objeto string en C#. Esta es la razón completa por la que existe StringBuilder.

3

Además de la respuesta de @ fretje anterior, en C# 6 y posterior, ahora se ha implementado getter-only auto properties, lo que permite propiedades automáticas inmutables sin la necesidad del campo de respaldo explícito adicional private readonly. El código equivalente se abrevia:

class ImmutableType 
{ 
    public string Test 
    { 
     get; // No Set at all, not even a private set. 
    } 

    public ImmutableType(string test) 
    { 
     Test = test; // The compiler understands this and initializes the backing field 
    } 
} 

Tenga en cuenta que private set (el más cercano a la inmutabilidad podría conseguir utilizando las propiedades de automóviles en versiones anteriores de C#) sólo proporciona una encapsulación restringido de cambio en la propiedad desde el interior de la misma clase, y por lo tanto no es verdad inmutable:

public string Test 
{ 
    get; 
    private set; // Not immutable, since this is still mutable from within the class 
} 

Más sobre la inmutabilidad

Como han dicho otros, un immutable Property es una propiedad que no puede cambiar una vez que se ha establecido. El ajuste del 'único valor' generalmente se hace en el constructor.

Un immutable Type es un tipo en el que todas las propiedades y campos (externamente visibles) son inmutables; por ejemplo, el tipo "Grabar" originalmente programado para C# 7 (hopefully now 8) hubiera sido un tipo inmutable. Otros ejemplos de tipos inmutables son Tuples, y todos anonymous classes.

Los campos inmutables deben calificarse con la palabra clave readonly en C#: el compilador se encarga de garantizar que ningún otro código intente cambiar el campo fuera del constructor.

Siempre que sea posible, la inmutabilidad de campos, variables y propiedades se considera una buena práctica, ya que reduce enormemente el área de superficie para errores (ya que los campos representan el estado de un objeto, evitando cambios en los campos reduce el número de estados).

El beneficio de la inmutabilidad es especialmente importante en los programas de subprocesos múltiples, donde dos o más subprocesos acceden simultáneamente al mismo objeto. Dado que múltiples hilos de lectura concurrentes pueden acceder de forma segura al valor de un campo o propiedad, el programador no necesita preocuparse por los problemas de seguridad de los hilos relacionados con el cambio al campo por otros hilos.

Un inconveniente común de la inmutabilidad cuando se trata de objetos complejos que consisten en múltiples objetos compuestos, es que todo el gráfico debe construirse 'de una vez', lo que puede llevar a un código desordenado.Una solución común aquí es usar el Builder pattern como un andamio, que permite construir una representación transitoria y mutable en pasos, y luego el objeto final e inmutable se obtiene en el paso final .Build().