2009-05-29 11 views
5

Si hago lo siguiente:¿El recolector de basura despeja objetos suscritos a eventos?

public class Test 
{ 
    public static void Main() 
    { 
     List<Person> persons = new List<Person> { new Person() }; 

     persons[0].Sneezing += new EventHandler(Person_Sneezing); 

     persons = null; 
    } 

    public static void Person_Sneezing(object sender, EventArgs e) 
    { 
     (sender as Person).CoverFace(); 
    } 
} 

¿La persona que estaba en persona [0] todavía existe en la memoria porque está Estornudos delegado tiene una referencia al método Person_Sneezing o se consigue recogido por el GC?

Respuesta

8

Esto será recopilado por el GC. Para mantenerse en la memoria un objeto se debe hacer referencia directa o indirectamente por ...

  1. Un valor en la pila
  2. Un valor arraigado en un GC manija fuerte
  3. Un caso esquina o dos estoy no está pensando en el momento

Esto no es así para el objeto en las personas [0]. Entonces será coleccionado

Por supuesto, suponiendo que el constructor de Person() no hace nada gracioso como agregarse a ThreadLocalStorage.

1

Además de las respuestas que ya tiene, debe tener cuidado en ejemplos más realistas.

Si su aplicación tiene una ventana principal que sobrevive mientras se ejecuta el programa, y ​​crea frecuentemente objetos de "corta duración" que alistan sus métodos para eventos en la ventana principal, entonces debe eliminar los objetos de esos eventos cuando ya no los necesite, porque de lo contrario esos objetos no serán "efímeros" en absoluto; sobrevivirán tanto como la ventana principal, es decir, hasta que el usuario cierre la aplicación. El resultado efectivo será equivalente a una pérdida de memoria.

Puede ayudar si la clase del objeto efímero implementa IDisposable, por lo que puede eliminar los eventos en Dispose, y luego asegurarse de llamar a deshacerse de los mismos cuando desee descartar un objeto.

6

Estás a medio camino; esto sería una pérdida de memoria si fuera el a la inversa. Es decir, si se veía así:

public class Test 
{ 
    public void HookupStuff() 
    { 
     List<Person> persons = new List<Person> { new Person() }; 

     this.EventHappened += new EventHandler(persons[0].SomeMethod); 
     // persons[0].Sneezing += new EventHandler(Person_Sneezing); 

     persons = null; 
    } 
} 

Ahora persons[0] se quedará, a pesar de que fuera anulado persons, ya que la clase padre tiene una referencia a un método en él.

+0

¿Lo llamarías una gotera? Si la prueba va bien, también lo hacen las personas [0]. –

+0

Claro, pero todo se va * finalmente * - en el peor de los casos, ¡desaparecerá cuando finalice su aplicación! Yo diría que es una filtración cuando no se va cuando crees que va a desaparecer. – mquander

+0

(Además, si no hizo otra referencia a personas [0], tendrá dificultades para recuperarla, por lo que básicamente se filtró a la nada). – mquander

Cuestiones relacionadas