2009-05-29 7 views
5

Se faccio la seguente:Il garbage collector cancella gli oggetti sottoscritti agli eventi?

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 che era in persona [0] esiste ancora nella memoria perché è Starnuti delegato ha un riferimento al metodo Person_Sneezing o lo fa ottiene raccolto dal GC?

risposta

8

Questo sarà raccolto dal GC. Da tenere in memoria un oggetto deve essere referenziato direttamente o indirettamente da ...

  1. Un valore sullo stack
  2. Un valore radicato in una forte GC gestire
  3. Un caso angolo o due sono non pensare al momento

Questo non è vero per l'oggetto alle persone [0]. Quindi sarà raccolto.

Questo è ovviamente presupponendo che il costruttore di Person() non faccia nulla di divertente come si aggiunge a ThreadLocalStorage.

1

Oltre alle risposte che hai già ottenuto, devi fare attenzione a esempi più realistici.

Se l'applicazione ha una finestra principale che sopravvive fintanto che il programma è in esecuzione e si creano frequentemente oggetti "di breve durata" che integrano i loro metodi con gli eventi nella finestra principale, è necessario rimuovere gli oggetti da quegli eventi quando non ne hai più bisogno, perché altrimenti quegli oggetti non saranno affatto "di breve durata" - sopravviveranno finché la finestra principale, cioè finché l'utente non chiude l'applicazione. Il risultato effettivo sarà equivalente a una perdita di memoria.

Può essere d'aiuto se si realizza l'oggetto di classe dell'oggetto di breve durata IDisposable, in modo da poter cancellare gli eventi in Dispose, quindi assicurarsi di chiamare il dispositivo quando si desidera scartare un oggetto.

6

Sei a metà strada; questa sarebbe una perdita di memoria se fosse il in un altro modo. Cioè, se si presentava così:

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; 
    } 
} 

Ora persons[0] si attacchi in giro, anche se annullato fuori persons, dal momento che la classe padre ha un riferimento a un metodo su di esso.

+0

La chiamereste una perdita? Se Test va via, anche le persone [0]. –

+0

Certo, ma tutto scompare * alla fine * - nel peggiore dei casi, tutto andrà via quando l'applicazione si chiude! Lo chiamerei una perdita quando non se ne va quando pensi che andrà via. – mquander

+0

(Inoltre, se non hai fatto un altro riferimento alle persone [0], ti sarà difficile tornare indietro, quindi è praticamente trapelato nel nulla.) – mquander

Problemi correlati