Crad's .NET Blog

L'UGIblog di Marco De Sanctis
posts - 190, comments - 457, trackbacks - 70

Dispose serve a liberare memoria?

Stavo rispondendo a questo post di Andrea Moro quando alla fine mi sono reso conto di essere un po' prolisso, e allora ho pensato di esternare le mie elucubrazioni qui

Volevo fare una piccola precisazione per quanto riguarda l'interfaccia IDisposable, perché leggo spesso che si fa molta confusione su quest'aspetto: richiamare il metodo Dispose *NON* serve a liberare memoria.
A cosa serve allora? Sapete che per ogni classe posso scrivere un Finalizer, ad es. per liberare delle risorse unmanaged che la mia classe utilizza (si pensi ad un file aperto con un'istanza di FileStream). A differenza di altri linguaggi, però, i finalizer nel CLR non sono direttamente invocabili, ma possono essere eseguiti solo dal Garbage Collector, che per sua natura è non deterministico (come è stato giustamente detto nel post di cui sopra).

Ora, dato che non è bello mantenere impegnata una risorsa fino ad una garbage collection che non si sa se e quando arriverà, si può implementare il pattern IDisposable in modo da rilasciarla in maniera deterministica, e cioé quando sappiamo che non ci servirà più! Ma attenzione, perché fino a che non avviene la collect, l'oggetto (questa volta senza risorse unmanaged impegnate, e quindi "innocuo") è ancora lì bel bello nel managed heap!

Il vantaggio di IDisposable, però, non è solo questo; per il GC distruggere una classe che presenta un finalizzatore è cosa parecchio onerosa: essa infatti necessita di due cicli di garbage collecting per essere distrutta! Nel primo viene creata una reference alla stessa in una coda chiamata FReachableQueue per eseguirne il Finalizer, nel secondo viene effettivamente liberata la memoria. Con IDisposable, invece, dato che il finalizzatore non deve più essere invocato dal GC (perché l'abbiamo esplicitamente eseguito noi da codice), il GC può distruggere l'oggetto direttamente. Ecco perché una best-practice è quella di terminare ogni metodo Dispose con l'istruzione

GC.SuppressFinalize(this)

con la quale viene indicato al GC che non è più necessario eseguire il finalizer per questa specifica istanza.

Spero di non aver scritto castronerie!

Ciauuu!

powered by IMHO 1.3

Print | posted on sabato 27 maggio 2006 00:06 | Filed Under [ .Net 2.0 ]

Powered by:
Powered By Subtext Powered By ASP.NET