Las dos mejores opciones para un objeto de transferencia de datos generalmente deben ser un objeto de clase profundamente inmutable o una estructura con campos expuestos de tipos adecuados para su uso como objetos de transferencia de datos. También se pueden usar otros tipos de estructuras, pero las estructuras de campo expuesto son de lejos las más simples, y esa simplicidad es una gran virtud.
La noción de que estructuras mutables son las fechas del mal de nuevo a algunos de los primeros C# Compiladores la que en la que
SomeReadonlyStruct.SomeProperty = 5;
estaría en silencio transformar por el compilador en:
var temp = SomeReadonlyStruct;
temp.SomeProperty = 5;
Ocultación campos struct detrás de propiedades de sólo lectura fue un intento de asegurar que la declaración anterior se negara a compilar en lugar de producir código roto. Debido a que los compiladores más nuevos se negarán a mutar campos escribibles de estructuras de solo lectura, ya no es necesario ajustar los campos en propiedades de solo lectura.
Las estructuras con campos expuestos tienen una gran ventaja comparadas con otros tipos de objetos de transferencia de datos: cada estructura que tiene campos expuestos de tipos adecuados para transferencia de datos y ningún otro miembro excepto tal vez un constructor se comporta de la misma manera, sin sorpresas Alguien que nunca ha usado las estructuras podría estar un poco sorprendido por el hecho de que no actúan como clases, pero alguien que entienda cómo funciona una estructura así entenderá cómo funcionan todas.
considere el siguiente código:
customerPhone = someDataSource.GetPhoneNumber(customerID);
customerPhone.Extention = "5309"
Algunas personas no les gusta el hecho de que si customerPhone
es una estructura de campo expuesta, estableciendo la propiedad Extension
no afectará a la información en someDataSource
. Si bien es cierto que escribir un campo de estructura no actualizará nada más, esa es una situación mucho mejor de la que existiría si customerPhone
fuera un tipo de clase mutable. Cualquiera que entienda que customerPhone
es un tipo de estructura de campo expuesto sabrá que los cambios en sus miembros no afectarán a nada más. Por el contrario, si customerPhone
es un tipo de clase mutable, el código como el anterior puede actualizar someDataSource
cambiando el número de teléfono asociado con ese customerID
. O tal vez no. O bien, si un número de teléfono se asoció con dos valores de customerID
, el código anterior podría cambiarlos a ambos. La cantidad de código que uno debe estudiar para determinar exactamente qué efectos y efectos secundarios podría tener el código anterior sería bastante grande. Peor aún, puede ser difícil estar seguro de que uno no se haya perdido nada.
Definitivamente, hay algunos lugares donde pasar referencias de objetos de clase puede ser más eficiente que pasar estructuras. También hay unos pocos casos donde los objetos de clase mutables pueden ser portadores de datos útiles dentro de una clase. Algunos contenedores genéricos, sin embargo, pueden faclitate envolviendo una estructura en una clase mutable o inmutable, e intercambiando la información entre esos tipos de clases.
interface IReadableHolder<T> { T Value {get;} }
class MutableHolder<T> : IReadableHolder<T>
{
public T Value;
IReadableHolder.Value {get {return Value;} }
public MutableHolder(T newValue) { Value = newValue; }
public MutableHolder(IReadableHolder<T> it) { Value = it.Value; }
}
class ImmutableHolder<T> : IReadableHolder<T>
{
T _Value;
public Value {get {return _Value;} }
public ImmutableHolder(T newValue) { _Value = newValue; }
}
Tal construcción sería mucho más incómoda sin estructuras mutables.
"clase" (que fue fácil; p) –
¡Gracias a todos por participar! –