2009-07-02 10 views

risposta

22

Sì, sì. Gli editori dell'evento sono in possesso di riferimenti agli oggetti e impedirebbero loro di raccogliere dati inutili.

Diamo un'occhiata a un esempio per vedere cosa succede. Abbiamo due classi; si espone un evento, l'altro si consuma:

class ClassA 
{ 
    public event EventHandler Test; 
    ~ClassA() 
    { 
     Console.WriteLine("A being collected"); 
    } 
} 
class ClassB 
{ 
    public ClassB(ClassA instance) 
    { 
     instance.Test += new EventHandler(instance_Test); 
    } 

    ~ClassB() 
    { 
     Console.WriteLine("B being collected"); 
    } 

    void instance_Test(object sender, EventArgs e) 
    { 
     // this space is intentionally left blank 
    } 
} 

noti come ClassB non memorizza un riferimento all'istanza ClassA; semplicemente collega un gestore di eventi.

Ora, vediamo come vengono raccolti gli oggetti. Scenario 1:

ClassB temp = new ClassB(new ClassA()); 
Console.WriteLine("Collect 1"); 
GC.Collect(); 
Console.ReadKey(); 
temp = null; 
Console.WriteLine("Collect 2"); 
GC.Collect(); 
Console.ReadKey(); 

Creiamo un'istanza di ClassB e ne manteniamo un riferimento tramite la variabile temp. Viene passata una nuova istanza di ClassA, in cui non viene memorizzato alcun riferimento a esso in alcun modo, quindi esce dall'ambito immediatamente dopo l'esecuzione del costruttore ClassB. Abbiamo il garbage collector eseguito una volta quando ClassA è andato fuori portata, e una volta quando ClassB è andato fuori ambito. L'output:

Collect 1 
A being collected 
Collect 2 
B being collected 

Scenario 2:

ClassA temp = new ClassA(); 
ClassB temp2 = new ClassB(temp); 
temp2 = null; 
Console.WriteLine("Collect 1"); 
GC.Collect(); 
Console.ReadKey(); 
temp = null; 
Console.WriteLine("Collect 2"); 
GC.Collect(); 
Console.ReadKey(); 

viene creata una nuova istanza di ClasseA e un riferimento è memorizzato nella variabile temporanea. Quindi viene creata una nuova istanza di ClassB, ottenendo l'istanza ClassA in temp passata ad esso e memorizziamo un riferimento ad esso in temp2. Quindi impostiamo temp2 su null, rendendo l'istanza ClassB fuori dal campo di applicazione. Come prima, abbiamo il garbage collector eseguito dopo ogni istanza è andato fuori portata. L'output:

Collect 1 
Collect 2 
B being collected 
A being collected 

Quindi, per concludere; se l'istanza che espone un evento esce dall'ambito, diventa disponibile per la garbage collection, indipendentemente dal fatto che ci siano o meno gestori di eventi collegati. Se un'istanza che ha un gestore eventi collegato a un evento in un'altra istanza, non sarà disponibile per la garbage collection finché il gestore eventi non viene rimosso o l'istanza a cui è collegato il gestore eventi diventa disponibile per la garbage collection.

9

Hai solo bisogno di sganciare gli eventi se l'oggetto esponendo eventi è longevo, ma l'oggetto aggancio l'evento sarebbe altrimenti essere di breve durata (e ottenere garbage collection abbastanza rapidamente).

In questo caso, non riuscire a sganciare causerà una perdita di memoria, perché il tuo oggetto di breve durata non sarà in grado di essere sottoposto a GC, perché l'evento nell'oggetto a lunga durata rimane su un delegato, che contiene un riferimento all'oggetto di breve durata. Poiché l'oggetto di breve durata è ancora referenziato da quel delegato, non può ottenere la raccolta di dati inutili.

Gli eventi statici sono longevi per definizione: vivono fino all'uscita dal programma. Se si aggancia un evento statico, è assolutamente necessario sganciarlo quando hai finito.

Se entrambi gli oggetti stanno per essere orfani, lo sganciamento non è necessario.

5

L'iscrizione a un evento comporta un forte riferimento al sottoscrittore. Questo perché, sotto le copertine, gli eventi sono delegati e i delegati ai metodi di istanza sono una combinazione del riferimento all'oggetto e del metodo effettivo. Se non annulli l'iscrizione, il publisher continuerà a mantenere i riferimenti e gli oggetti sottoscrittori non diventeranno mai orfani (e GC) finché il publisher sarà vivo.

Il contrario non è vero, ad esempio l'oggetto sottoscritto non ha alcun riferimento all'editore.

Problemi correlati