Respuesta corta, no, o
serán liberados. No te preocupes por eso respuesta
Ligeramente más largo:
Su código hace más o menos lo siguiente:
- crear un poco de almacenamiento local en ese hilo para una referencia a los nuevos MiClase (
o
).
- Crea la nueva MyClass
- Guarda una referencia a la nueva MyClass en
o
.
- Crea un nuevo delegado de la lambda.
- Asigna que el delegado al evento (
o
ahora tiene una referencia al delegado).
En cualquier punto durante esto, el GC puede detener los hilos y luego examinar qué objetos están enraizados o no. Las raíces son objetos que están estáticos o en el almacenamiento local de un hilo (me refiero a las variables locales en la ejecución de un hilo dado, implementadas por una pila, en lugar de "Thread-Local Storage", que es esencialmente una forma de estática). Los objetos enraizados son raíces, objetos a los que hacen referencia, objetos a los que hacen referencia, etc. Los objetos enraizados no se recopilarán, el resto lo hará (salvo que se hagan algunas cosas extra con los finalizadores, lo ignoraremos por el momento).
En ningún momento hasta ahora después de la creación del objeto MyClass no ha sido rooteado por el almacenamiento local del hilo.
En ningún punto hasta ahora después de que el objeto delegado que se está creando no haya sido rooteado por el almacenamiento local del subproceso o por el hecho de que MyClass tenga una referencia al mismo.
Ahora, ¿qué pasa después?
Depende. La lambda no mantendrá viva la MyClass (la MyClass la mantiene viva, pero cuando la MyClass se va, también lo hace la lambda). Esto no es suficiente para responder "¿Serán elegibles para la recolección de basura aquí?" aunque.
void Meth0()
{
var o = new MyClass();
o.MyClassEvent += (args) => {};
}//o is likely eligible for collection, though it doesn't have to be.
void Meth1()
{
int i = 0;
{
var o = new MyClass();
o.MyClassEvent += (args) => {};
}//o is likely not eligible for collection, though it could be.
while(i > 100000000);//just wasting time
}
void Meth2()
{
{
var o = new MyClass();
o.MyClassEvent += (args) => {};
int i = 0;//o is likely eligible for collection, though it doesn't have to be.
while(i > 100000000);//just wasting time
}
}
void Meth3()
{
{
var o = new MyClass();
o.MyClassEvent += (args) => {};
var x0 = new MyClass();//o is even more likely eligible for collection, though it doesn't have to be.
var x1 = new MyClass();//o is even more likely eligible for collection, though it doesn't have to be.
var x2 = new MyClass();//o is even more likely eligible for collection, though it doesn't have to be.
var x3 = new MyClass();//o is even more likely eligible for collection, though it doesn't have to be.
var x4 = new MyClass();//o is even more likely eligible for collection, though it doesn't have to be.
var x5 = new MyClass();//o is even more likely eligible for collection, though it doesn't have to be.
var x6 = new MyClass();//o is even more likely eligible for collection, though it doesn't have to be.
var x7 = new MyClass();//o is even more likely eligible for collection, though it doesn't have to be.
var x8 = new MyClass();//o is even more likely eligible for collection, though it doesn't have to be.
var x9 = new MyClass();//o is even more likely eligible for collection, though it doesn't have to be.
var x10 = new MyClass();//o is even more likely eligible for collection, though it doesn't have to be.
var x11 = new MyClass();//o is even more likely eligible for collection, though it doesn't have to be.
int i = 0;
while(i > 100000000);//just wasting time
}
}
Meth0 es aparentemente el más sencillo, pero en realidad no lo es, así que va a volver a ella.
En meth1, la aplicación es probable estar dejando el almacenamiento local tal como es, ya que no ha necesitado más, así que mientras o
no está en el alcance, la aplicación tendrá aún que el almacenamiento local en uso.
En meth2, la implementación podría utilizar el mismo almacenamiento local que estaba utilizando para o
para i
así que, aunque todavía en su alcance, sería elegible para recibir ("alcance" quiere decir que el programador podría optar por hacer algo con eso, pero él o ella no y el código compilado no tiene necesidad de tal concepto).
Meth3 es más probable que vuelva a utilizar el almacenamiento, debido a que los usos temporales adicionales de la misma hacen que la aplicación frente dejando a un lado todo el almacenamiento, para empezar, tendría más sentido.
Ninguna de estas cosas tiene de esta manera. Meth2 y Meth3 podrían dejar de lado todo el almacenamiento necesario para el método al principio. Meth1 podría reutilizar el almacenamiento porque no tiene importancia reordenar i
y o
asignados.
Meth0 es más complicado, ya que podría depender de lo que el método de llamada hace junto con el almacenamiento local, en lugar de estar allí una limpieza en el momento (ambos son implementaciones legítimos). IIRC siempre hay una limpieza con la implementación actual, pero no estoy seguro y no importa de todos modos.
En total, el alcance no es lo relevante, pero si el compilador y más tarde el jitter puede y hace uso del almacenamiento local en relación con un objeto. Incluso es posible limpiar un objeto antes de que se invoquen los métodos y las propiedades (si esos métodos y propiedades no utilizan this
o cualquiera de los campos del objeto, porque funcionará muy bien si el objeto se ha eliminado).)
Debe ser elegible para GC. No estoy seguro de esto para convertirlo en una respuesta. –
No veo por qué esto se comportaría de manera diferente a la suscripción de cualquier otra función (lambda o no) a un evento. Así que estoy de acuerdo con Tim. –
posible duplicado de [La recolección de basura cuando se utiliza delegados anónimos para el manejo de eventos] (http://stackoverflow.com/questions/371109/garbage-collection-when-using-anonymous-delegates-for-event-handling) –