Pregunta

  

Posible duplicado:
   ¿Por qué las estructuras mutables son malas?

Lo leí en muchos lugares, incluido aquí, que es mejor hacer estructuras como inmutables.

¿Cuál es la razón detrás de esto? Veo muchas estructuras creadas por Microsoft que son mutables, como las de xna. Probablemente hay muchos más en el BCL.

¿Cuáles son las ventajas y desventajas de no seguir esta directriz?

¿Fue útil?

Solución

Las estructuras deben representar valores . Los valores no cambian. El número 12 es eterno.

Sin embargo, considere:

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

Ahora foo.Bar y foo.B.Bar son diferentes, lo que a menudo es inesperado. Especialmente en escenarios como propiedades (afortunadamente el compilador lo detecta). Pero también colecciones, etc. ¿Cómo los mutas sensiblemente?

La pérdida de datos es demasiado fácil con estructuras mutables.

Otros consejos

La gran desventaja es que las cosas no se comportan como espera que lo hagan, especialmente si la mutabilidad proviene de una mezcla del valor directo y un tipo de referencia dentro de él.

Para ser honesto, no puedo recordar de la cabeza todos los problemas extraños que he visto a las personas en grupos de noticias cuando han usado estructuras mutables, pero esas razones ciertamente existen. Las estructuras mutables causan problemas. Manténgase alejado.

EDITAR: Acabo de encontrar un correo electrónico que escribí hace un tiempo sobre este tema. Se elabora solo un poco:

  • Es filosóficamente incorrecto: una estructura debe representar algún tipo de valor fundamental. Esos son básicamente inmutables. No puede cambiar el número 5. Puede cambiar el valor de una variable de 5 a 6, pero lógicamente no hace un cambio en el valor en sí.

  • Es prácticamente un problema: crea muchas situaciones extrañas. Es particularmente malo si es mutable a través de una interfaz. Entonces puede comenzar a cambiar los valores en recuadro. Ick He visto muchas publicaciones de grupos de noticias que se deben a que las personas intentan usar estructuras mutables y se encuentran con problemas. Vi un ejemplo LINQ muy extraño que estaba fallando porque List<T>.Enumerator es una estructura, por ejemplo.

Utilizo estructuras mutables a menudo en mi proyecto (crítico para el rendimiento), y no me encuentro con problemas, porque entiendo las implicaciones de la semántica de copia. Por lo que puedo decir, la razón principal por la que las personas abogan por estructuras inmutables es para que las personas que no entiendan las implicaciones no puedan meterse en problemas.

Eso no es algo tan terrible, pero ahora estamos en peligro de que se convierta en " la verdad del evangelio " ;, cuando en realidad hay momentos en los que es legítimamente la mejor opción para hacer un estructura mutable. Como con todas las cosas, hay excepciones a la regla.

No hay nada más barato de manipular que una estructura mutable, por lo que a menudo lo ves en un código de alto rendimiento como las rutinas de procesamiento de gráficos.

Desafortunadamente, las estructuras mutables no funcionan bien con objetos y propiedades, es demasiado fácil modificar una copia de un objeto en lugar de la estructura misma. Por lo tanto, no son apropiados para la mayoría de su código.

P.S. Para evitar el costo de copiar estructuras mutables, generalmente se almacenan y pasan en matrices.

La razón técnica es que las estructuras mutables aparecen para poder hacer cosas que en realidad no hacen. Dado que la semántica en tiempo de diseño es la misma que los tipos de referencia, esto se vuelve confuso para los desarrolladores. Este código:

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

Se comporta de manera bastante diferente dependiendo de si MySomething es un struct o un class. Para mí, esta es una razón convincente, pero no la más convincente. Si nos fijamos en DDD 's Value Object , puede ver la conexión sobre cómo deben tratarse las estructuras. Un objeto de valor en DDD se puede representar mejor como un tipo de valor en .Net (y, por lo tanto, una estructura). Como no tiene identidad, no puede cambiar.

Piense en esto en términos de algo como su dirección. Puede & Quot; cambiar & Quot; su dirección, pero la dirección en sí no ha cambiado. De hecho, tiene una nueva dirección asignada. Conceptualmente, esto funciona, porque si realmente cambiaste tu dirección, tus compañeros de cuarto también tendrían que mudarse.

Ha solicitado los pros y los contras de no siguiendo la directriz de que las estructuras deben ser inmutables.

Contras: Las desventajas están bien cubiertas en las respuestas existentes, y la mayoría de los problemas descritos se deben a la misma causa: comportamiento inesperado debido a la semántica del valor de las estructuras .

Pros: El principal profesional del uso de estructuras mutables puede ser rendimiento . Obviamente, este consejo viene con todas las advertencias habituales sobre optimizaciones: asegúrese de que parte de su código necesita estar optimizado y asegúrese de que cualquier cambio realmente optimice el rendimiento de su código a través de la creación de perfiles.

Para un excelente artículo que discute cuándo podría querer usar estructuras mutables, vea Prueba de rendimiento sobre programación basada en el valor (o más específicamente, las respuestas ).

Una estructura generalmente debe representar una sola unidad de algún tipo. Como tal, no tiene mucho sentido cambiar una de las propiedades del valor, tiene más sentido crear un valor completamente nuevo si desea un valor que sea diferente de alguna manera.

La semántica se vuelve más simple cuando se usan estructuras inmutables, y se evitan errores 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;

El resultado es que la estructura en la lista no cambia en absoluto. La expresión Intervalo [0] copia el valor de la estructura de la lista, luego cambia la propiedad del valor temporal, pero el valor nunca se vuelve a colocar en la lista.

Editar: se modificó el ejemplo para usar una lista en lugar de una matriz.

Cuando copie estructuras a su alrededor, copie su contenido, por lo que si modifica una versión copiada, " original " no se actualizará.

Esta es una fuente de errores, ya que incluso si sabe que cae en la trampa de copiar una estructura (simplemente pasándola a un método) y modificar la copia.

Me sucedió nuevamente la semana pasada, me mantuvo una hora buscando un error.

Mantener las estructuras inmutables evita que ...

Aparte de eso, debes asegurarte de tener una muy buena razón para usar estructuras en primer lugar: " optimización " o " Quiero algo que se asigne rápidamente en la pila " No cuenta como respuesta. Reorganización o cosas en las que depende del diseño: está bien, pero normalmente no debe mantener esas estructuras durante mucho tiempo, son valores, no objetos.

la razón por la que debe hacer que las estructuras sean inmutables es que son ValueTypes , lo que significa que se copian cada vez que los pasa a un método.

Entonces, si, por ejemplo, tuviera una propiedad que devolviera una estructura, modificar el valor de un campo en esa estructura no tendría ningún valor, porque el captador devolvería una copia de la estructura, más bien que una referencia a la estructura. He visto esto hecho en código, y a menudo es difícil de atrapar.

Si diseñas tus estructuras para la inmutabilidad, ayudas al programador a evitar estos errores.

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