¿Las estructuras son siempre stack asignadas o a veces heap asignadas?


Tenía la impresión de que en C#, los elementos struct se asignan en la pila y, por lo tanto, desaparecen al regresar de un método en el que se crearon. Pero, ¿qué sucede si pongo los valores de estructura en una lista y devuelvo eso? Los elementos sobreviven. ¿A veces se asignan instancias de estructura en el montón?

internal struct Stru
{
  public int i;
}

internal class StruTry
{
  public List<Stru> Get(int max)
  {
    var l = new List<Stru>();
    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);
}
Author: user2864740, 2011-01-31

6 answers

Primero, lea este post de Eric Lippert en La Pila es un Detalle de Implementación. Síguelo con La Verdad sobre los Tipos de Valor. En cuanto a su pregunta específica

¿A veces se asignan instancias de estructura en el montón?

Sí, a veces se asignan en el montón. Hay un montón de ejemplos de cuando podrían ser asignados en el montón. Si están en caja, o si son campos de una clase, o si son elementos de una matriz, o si son el valor de una variable de tipo value que ha sido cerrada, etc.

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

Estás pensando en esto de la manera correcta, y este es uno de los puntos más destacados sobre dónde se podría asignar un tipo de valor. Vea el segundo post al que me referí sobre La Verdad sobre los Tipos de Valor para más detalles. Pero solo mantener La Pila es un Detalle de Implementación en mente. La clave es que realmente no necesitas preocuparte por estas cosas. Debe preocuparse por la diferencia semántica entre los tipos de valor y los tipos de referencia.

 47
Author: jason,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-01-31 16:28:04

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

 15
Author: Marcelo Cantos,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-01-31 16:23:07

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

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

 5
Author: Trisped,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-17 17:45:16

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

 1
Author: fearofawhackplanet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-01-31 16:23:24

Por lo que recuerdo...

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

¡Avísame si me equivoco!

 1
Author: Matthew Abbott,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-01-31 16:24:17

Una ubicación de almacenamiento (variable, campo, parámetro, ranura de matriz, etc.) de tipo struct contiene los campos públicos y privados de la estructura dentro de ella. Si esa ubicación de almacenamiento está en la pila, los campos de la estructura estarán en la pila. Si está dentro de otra clase o estructura, entonces 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 clase contiene una referencia a un objeto de clase completo que siempre es (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.

 1
Author: supercat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-15 20:28:06