frecuencia leo que struct
s deben ser inmutables - ¿no son por definición?¿Los tipos de valor son inmutables por definición?
¿Considera int
ser inmutable?
int i = 0;
i = i + 123;
parece estar bien - tenemos una nueva int
y asignamos de nuevo a i
. ¿Qué hay de esto?
i++;
De acuerdo, podemos considerarlo un atajo.
i = i + 1;
Qué pasa con el struct
Point
?
Point p = new Point(1, 2);
p.Offset(3, 4);
¿Esto realmente mutar el punto (1, 2)
? ¿No deberíamos pensar en ello como un atajo para lo siguiente con Point.Offset()
devolviendo un nuevo punto?
p = p.Offset(3, 4);
El trasfondo de este pensamiento es este: ¿cómo puede ser mutable un tipo de valor sin identidad? Tienes que mirarlo al menos dos veces para determinar si cambió. Pero, ¿cómo puedes hacer esto sin una identidad?
no quiero complicar el razonamiento acerca de esto considerando ref
parámetros y el boxeo. También sé que p = p.Offset(3, 4);
expresa la inmutabilidad mucho mejor que p.Offset(3, 4);
. Pero la pregunta sigue siendo: ¿no son los tipos de valores inmutables por definición?
ACTUALIZACIÓN
Creo que hay al menos dos conceptos involucrados - la mutabilidad de una variable o campo y la mutabilidad del valor de una variable.
public class Foo
{
private Point point;
private readonly Point readOnlyPoint;
public Foo()
{
this.point = new Point(1, 2);
this.readOnlyPoint = new Point(1, 2);
}
public void Bar()
{
this.point = new Point(1, 2);
this.readOnlyPoint = new Point(1, 2); // Does not compile.
this.point.Offset(3, 4); // Is now (4, 6).
this.readOnlyPoint.Offset(3, 4); // Is still (1, 2).
}
}
En el ejemplo tenemos campos a, uno mutable e inmutable. Como un campo de tipo de valor contiene el valor completo, un tipo de valor almacenado en un campo inmutable también debe ser inmutable. Todavía estoy bastante sorprendido por el resultado: no esperaba que el campo de solo lectura permanezca sin modificaciones.
Variables (además de constantes) son Allways mutable, por lo tanto, implican ninguna restricción sobre la mutabilidad de los tipos de valor.
La respuesta no parece ser tan sencilla, por lo que voy a reformular la pregunta.
Dada la siguiente.
public struct Foo
{
public void DoStuff(whatEverArgumentsYouLike)
{
// Do what ever you like to do.
}
// Put in everything you like - fields, constants, methods, properties ...
}
le puede dar una versión completa de Foo
y un ejemplo de uso - que puede incluir ref
parámetros y el boxeo - de modo que no es posible volver a escribir todas las apariciones de
foo.DoStuff(whatEverArgumentsYouLike);
con
foo = foo.DoStuff(whatEverArgumentsYouLike);
Agregué este comentario a varias respuestas antes. Podría reescribir p.X = 5; como p = p.SetX (5) ;. Si siempre puedo hacer esto -la semántica del tipo de valor puede permitir esto, pero no estoy seguro- podría considerar que la estructura es inmutable o equivalente a una estructura inmutable. Así que reformulé la pregunta: ¿puedo hacer esta transformación siempre? Si es así, esto implica que las estructuras son inmutables porque puedo reescribirlas de una manera que hace inmutable la inmutabilidad. –
@Daniel: No estoy seguro de seguirte. Si puede hacer p.X = 5, el tipo es mutable. Si p2 = p1.SetX (5) no cambia p1, y no hay forma de cambiar p1, entonces es inmutable. Tenga en cuenta que p = p.SetX (5) está reemplazando el valor de p con uno nuevo, sin modificar el valor original. – Lucas
Usted es absolutamente correcto. Y como p es un tipo de valor y no puede tener una referencia, no debería importar si modifica el valor almacenado en p o lo reemplaza con una versión modificada. Si encuentras un ejemplo donde esto importa, tal vez algo que involucre parámetros de ref, boxeo, o algo que ni siquiera he pensado (actualmente estoy pensando en las propiedades del tipo de valor), entonces estoy equivocado y las estructuras son mutables. Si siempre puedo transformar myStruct.ChangeStuff() en myStruct = myStruct.ChangeStuff(), entonces puedo considerar que las estructuras son inmutables. –