¿Las estructuras siempre se asignan o, a veces, se asignan?

Tenía la impresión de que en C #, los elementos struct se asignan en la stack y desaparecen cuando regresan de un método en el que se crearon. Pero, ¿qué sucede si coloco los valores de estructura en una lista y lo devuelvo? Los elementos sobreviven ¿Las instancias de las estructuras a veces se asignan en el montón?

internal struct Stru { public int i; } internal class StruTry { public List Get(int max) { var l = new List(); for (int i = 0; i < max; i++) l.Add(new Stru {i=i}); return l; } } 

código de impresión 0, 1, 2

 [Test] public void T() { var ll = new StruTry().Get(3); foreach (var stru in ll) Console.WriteLine("* "+ stru.i); } 

Primero, lea esta publicación de Eric Lippert en The Stack es un detalle de implementación . Síguelo con The Truth about Value Types . En cuanto a su pregunta específica

¿Las instancias de las estructuras a veces se asignan en el montón?

Sí, a veces se asignan en el montón. Hay muchos ejemplos de cuándo podrían asignarse en el montón. Si están encasilladas, o si son campos de una clase, o si son elementos de una matriz, o si son el valor de una variable de tipo de valor que se ha cerrado, etc.

Pero, ¿qué sucede si coloco los valores de estructura en una lista y lo devuelvo? Los elementos sobreviven

Está pensando en esto de la manera correcta, y este es uno de los puntos más importantes sobre dónde se podría asignar un tipo de valor. Vea la segunda publicación a la que me referí en La verdad sobre los tipos de valores para más detalles. Pero simplemente mantenga The Stack es un detalle de implementación en mente. El punto clave es que realmente no necesita preocuparse por esto. Debería preocuparse por la diferencia semántica entre los tipos de valores y los tipos de referencia.

Las estructuras son como los Ints. Si tiene un int local, generalmente estará en la stack, si tiene una lista de entradas, se almacenan directamente en la matriz interna de la lista, que está en el montón. Las estructuras se comportan de la misma manera.

Pero, ¿qué sucede si coloco los valores de estructura en una lista y lo devuelvo? Los elementos sobreviven

Técnicamente, los valores agregados a la ‘Lista’ no son los mismos valores, son copias basadas en valores. Si, por ejemplo, modificas el original, esos cambios no se llevarán a la copia de la lista. Además, ‘Lista’ devuelve una copia del valor en el índice indicado. Esto significa que si la estructura es mutable y usted modifica el valor devuelto desde la ‘Lista’, entonces el valor en la List permanecerá sin cambios. Este no es el caso con las matrices, ya que el índice de la matriz proporciona acceso a la variable real.

Todos los tipos pueden asignarse en algún momento en el montón. Además, heap / stack es un detalle de implementación del CLR y no de la especificación C #, por lo que nunca deberías confiar en tales cosas. Vea aquí una buena publicación en el blog sobre este tema.

Por lo que recuerdo …

La ubicación de los tipos de valores depende de dónde se declaran. Las variables de método se asignan, se almacenan en la stack y se eliminan después de la ejecución del método en el marco de la stack. Los tipos de valor declarados como parte de un tipo de referencia se almacenan en el montón dentro de la estructura del tipo adjunto.

¡Avíseme si estoy equivocado!

Una ubicación de almacenamiento (variable, campo, parámetro, ranura de matriz, etc.) del tipo de estructura contiene los campos públicos y privados de la estructura dentro de ella. Si esa ubicación de almacenamiento está en la stack, los campos de la estructura estarán en la stack. Si está dentro de otra clase o estructura, los campos de la estructura se almacenarán como parte de esa otra clase o instancia de estructura .

Una ubicación de almacenamiento de tipo de clase contiene una referencia a un objeto de clase completo que siempre está (1) almacenado en algún lugar completamente separado de la ubicación de almacenamiento que contiene una referencia, o (2) el objeto de clase del cual esa ubicación de almacenamiento es un campo.