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

4 Comments Filed Under [ .Net 2.0 ]

Comments

# re: Dispose serve a liberare memoria?
Gravatar ciao Marco, sul fatto che implementare IDispose non serve a liberare memoria è effettivamente una cosa che sin dai primi anni di .NET aveva tratto in inganno molti programmatori.... e ogni tanto - come ai giustamente fatto in questo post - è bene rikordare la kosa :-p Non sempre è chiara la distinzione tra risorse gestite (la memoria) e risorse NON gestite (tutte le altre). Un buon approfondimento è "Intervista a Eric Gunnerson: Garbage Collection e finalizzazione degli oggetti", http://www.ugidotnet.org/articles/articles_read.aspx?ID=53 (Raffaele Rialdi, Settembre 2003 - roba d'annata :-p)
Left by M.rkino on 27/05/2006 16.59
# re: Dispose serve a liberare memoria?
Gravatar [ErrataKorrige] ke vergogna mi son perso una H: "come (H)ai giustamente fatto in questo post " :-p
Left by M.rkino on 27/05/2006 17.00
# re: Dispose serve a liberare memoria?
Gravatar Grazie omonimo, credo che ai tempi avessi già letto l'articolo di Raffaele, ma gli ridò volentieri un'occhiata, non si sa mai.

Quanto all'errorino ortografico... beh... dal correttore ufficiale di UGI non me lo sarei mai aspettato!! EHEHEHHEHE!!! :D (scherzo!)
Left by Marco De Sanctis on 27/05/2006 17.23
# re: Dispose serve a liberare memoria?
Gravatar Della serie, meno male che leggo il blog, altrimenti non avrei mai visto che mi avevi mezionato in tuo post :)

Ue che comincio a diventare famoso .... :P

Ciao
Andrea
Left by Andrea on 29/05/2006 14.20

Leave Your Comment

Title*
Name*
Email (never displayed)
 (will show your gravatar)
Url
Comment*

Please add 6 and 1 and type the answer here:

Preview Your Comment.