Si te enseñan el siguiente código, ¿cuál crees que es el resultado?
1: struct MutableStruct
2: {
3: private int x;
4: public int Mutate ( )
5: {
6: return ++x;
7: }
8: }
9:
10: class Program
11: {
12: public readonly MutableStruct _ms = new MutableStruct ();
13: static void Main ( string [] args )
14: {
15: Program _p = new Program ();
16: Console.WriteLine ( “Valor de la copia: {0} “,
17: _p._ms.Mutate ());
18: Console.WriteLine ( “Valor de la copia: {0} “,
19: _p._ms.Mutate () );
20: Console.WriteLine ( “Valor de la copia: {0} “,
21: _p._ms.Mutate ( ));
22: Console.ReadLine ();
23: }
24: }
El resultado puede sorprendernos a muchos. En realidad, no es 0, 0, 0 ni 1, 2, 3 sino 1,1,1. ¿Porqué? ¿cómo es eso? La cosa reside en la propia especificación del lenguaje C#. Recordemos que las struct son tipos de valor (value types), no referencias, es decir, son como un int y no como un objeto, como por ejemplo string. Por tanto, su valor no puede cambiar. Lo que ocurre es que al acceder a la struct en el código, obtenemos una copia de dicho valor, que no una referencia como ocurriría si accedieramos a un objeto, a una instancia de la clase “Producto”, por ejemplo, en nuestra aplicación. Es decir, que al hacer _p.ms estamos obteniendo una copia, y esa copia si es mutable, mientras que _m no lo es. Si modificamos el código ahora para comparar el valor original y la copia lo veremos más claro:
struct MutableStruct
{
private int x;
public int Mutate ( )
{
return ++x;
}
public override string ToString ( )
{
return String.Format ( “Valor de x: {0}”, x );
}
}
class Program
{
public readonly MutableStruct _ms = new MutableStruct ();
static void Main ( string [] args )
{
Program _p = new Program ();
Console.WriteLine ( “Valor de la copia: {0},{1}”,
_p._ms.Mutate (), _p._ms.ToString () );
Console.WriteLine ( “Valor de la copia: {0},{1}”,
_p._ms.Mutate (), _p._ms.ToString () );
Console.WriteLine ( “Valor de la copia: {0},{1}”,
_p._ms.Mutate ( ), _p._ms.ToString () );
Console.ReadLine ();
}
}
Al ejecutar veremos la siguiente salida por pantalla:
Valor de la copia: 1, Valor de x: 0
Valor de la copia: 1, Valor de x: 0
Valor de la copia: 1, Valor de x: 0
Esto nos permite ver que realmente lo único que cambia es el valor de la x interna de _p._ms, pero no cambia la variable asociada a ese campo, que sería la x privada que vemos en la definición de la struct.
Interesante ¿verdad?
Disclaimer: esto no se me ha ocurrido a mi, sino a Eric Lippert, pero me ha parecido muy interesante reproducirlo para trastear.
¿Y si le quitamos el readOnly?
Perdonad el formato, el editor es una puta mierda.
Saludos.