2010-03-30 12 views
7

Dato un oggetto, c'è un modo per ottenere la notifica di quando quell'oggetto è garbage collection?. NET: un modo per sapere quando un oggetto viene smaltito/eliminato?

Sto giocando con i metodi di estensione C# che si comportano un po 'più come mixin (in particolare nell'aggiunta della registrazione). Quindi praticamente ogni oggetto ottiene un nuovo metodo Logger() che restituisce un ILog che viene creato e memorizzato nella cache a seconda dell'oggetto che è il target del metodo di estensione.

Funziona molto bene, l'unica preoccupazione è ovviamente dopo che un oggetto va via il suo logger potrebbe rimanere in giro per un po 'di tempo. Ovviamente potrei impostare un meccanismo periodico per spazzare la cache del logger e cancellarlo, ma preferirei impostare una notifica di Garbage Collection in modo da sapere quando il sistema non usa più i miei oggetti.

Qualcuno sa di un modo per farlo?

risposta

11

Penso che in genere ciò che viene fatto è mantenere un elenco di WeakReferences. Con un riferimento debole, puoi stabilire se l'oggetto a cui ti stai riferendo è stato triturato o meno controllando la proprietà IsAlive.

+1

+1, maledizione, ha rubato la mia risposta haha ​​ – heisenberg

1

The destructor viene chiamato durante GC.

+1

Questo è divertente. Li ho sempre sentiti nominati "Finalizzatori". La nomenclatura è cambiata o mi sono sbagliato per tutto questo tempo? –

+1

Penso che ciò dipenda dalla lingua. Sembra che in C#, * destructor * si riferisca al costrutto linguistico che implementa * finalizzazione *. Tuttavia, in C++/CLI, il costrutto del linguaggio chiamato * destructor * (ad es. '~ Class() {...}') implementa effettivamente l'interfaccia * IDispose *, mentre esiste un nuovo costrutto di linguaggio chiamato * finalizzatore * (ad esempio ' ! class() {...} ') che è lo stesso di * distruttore * in C#. – stakx

+0

Sì, ma ciò significa che devo creare un distruttore che chiama qualcosa di simile.ReleaseLogger(). Non una cattiva idea, ma qualcosa che preferirei evitare. –

3

In .net 4.0, è presente un tipo ConditionalWeakTable che può essere utilizzato, anche se in modo un po 'scomodo, per richiedere la notifica quando un oggetto arbitrario diventa idoneo per la finalizzazione. Se un ConditionalWeakTable contiene una voce che associa un oggetto (ad esempio il 451 ° oggetto creato) a un altro oggetto (ad esempio il 730 ° oggetto creato), fino a quando la voce rimane nella tabella e i riferimenti radicati esistono sia alla tabella che all'oggetto # 451, la tabella sarà considerata un riferimento con radice all'oggetto # 730. Se non esiste alcun riferimento con radice all'oggetto # 451, la tabella cesserà di essere un riferimento con radice all'oggetto # 730.

Di conseguenza, se l'oggetto # 730 contiene un riferimento alla tabella e all'oggetto # 730 esiste all'esterno della tabella, l'oggetto # 730 diventerà idoneo per la finalizzazione contemporaneamente all'oggetto # 451. Se l'oggetto # 730 ha la precedenza su Finalize(), tale override può essere usato come notifica che l'oggetto # 451 è diventato idoneo per la finalizzazione.

Si noti che il finalizzatore dell'oggetto # 730 scatterà una sola volta anche se l'oggetto # 451 si resuscita e si registra nuovamente per la finalizzazione. Sarebbe possibile scrivere un codice che emetterebbe una notifica all'incirca nel momento in cui l'oggetto # 451 diventa veramente morto e sepolto, anche se viene risuscitato alcune volte prima, ma non c'è modo particolarmente pulito per farlo.

+0

Sarebbe fantastico avere una classe che gestisce questo e astrae il brutto, fornendo al client chiamante un'interfaccia carina, FWIW. Inoltre, da quello che sto leggendo, sembra che un oggetto possa essere resuscitato solo una volta? È esatto?Fonte: http://www.philosophicalgeek.com/2014/08/20/short-vs-long-weak-references-and-object-resurrection/ –

Problemi correlati