Los campos de clase, ¿están almacenados en la stack o en el montón?

Ayer vi una pregunta que planteó (para mí) otra pregunta. Por favor mira el siguiente código:

public class Class1 { int A; //as I uderstand, int is value type and therefore lives in the stack } class Class2 { Run() { Class1 instance1 = new Class1(); instance1.A = 10; //it points to value type, but isnt this reference (on heap)? } } 

¿O al crear la instancia de Class1, sus tipos de campo también se crean en el montón? Pero entonces no entiendo cuándo realmente estaría en la stack, ya que casi siempre necesitas crear una instancia de objeto para usar los campos.

según tengo entendido, int es un tipo de valor y, por lo tanto, vive en la stack

Tu comprensión es incorrecta Los tipos de valores se llaman “tipos de valor” porque se copian por valor. Los tipos de referencia se llaman “tipos de referencia” porque se copian por referencia. No es del todo cierto que “los tipos de valores siempre vivan en la stack”. Si eso fuera cierto, se llamarían “tipos de stack” y “tipos de montón”.

La verdad es que este es un detalle de implementación. Diferentes implementaciones de framework pueden elegir usar la stack y el montón como quieran. Así es como lo hace la implementación de Microsoft:

  • el valor de una variable del tipo de referencia es una referencia a la memoria del montón. Una referencia es básicamente un entero de 32 o 64 bits.
  • el valor de una variable de tipo de valor es su valor.
  • los valores de las variables locales se almacenan en la stack a menos que las variables locales estén en un bloque de iteradores o sean variables externas cerradas de un método anónimo o una expresión lambda. En esos casos, los valores de las variables locales se almacenan en el montón. A menos, por supuesto, que las variables locales puedan optimizarse, en cuyo caso no habrá almacenamiento. O tal vez se puedan registrar, en cuyo caso no están ni en la stack ni en el montón, están en los registros del procesador.
  • los valores de las variables de instancia de los tipos de referencia y las variables estáticas se almacenan en el montón.

¿Está claro?

apunta al tipo de valor, pero ¿no es esta referencia (en el montón)?

El campo “A” es de tipo de valor. Es un campo, y por lo tanto esa variable se almacena en el montón.

al crear la instancia de Clase 1, ¿sus tipos de campo también se crean en el montón?

El almacenamiento para las variables de instancia está en el montón, sí.

Pero entonces no entiendo cuándo realmente estaría en la stack, ya que casi siempre necesitas crear una instancia de objeto para usar los campos.

Nunca estaría en la stack. Como dije antes, las únicas cosas que van en la stack son las variables locales (y las temporales generadas por el comstackdor) que no son locales cerrados de un método lambda o anónimo y no están en un bloque iterador. Y, por supuesto, el jitter es libre de mantenerlos fuera de la stack por completo y ponerlos en registros si hay registros gratuitos.

Pero en realidad, tengo que preguntar, ¿por qué te importa lo que va en la stack y lo que sucede en el montón? Lo que pasa en la stack es algo que podemos poner barato en la stack; todo lo demás sigue en el montón.

Las variables de estructura local (tipo de valor) se almacenan en la stack, los campos de tipo de valor de una clase se almacenan en el montón.

Ok int es un tipo de valor pero ‘1’ (qué horrible nombre para una clase) es un tipo de referencia. Esto significa que cualquier instancia de ‘1’ está en el montón.