Marco Russo

.NET, Business Intelligence e dintorni

Corsi

Miei blog in inglese

Quando chiamare Dispose

Dopo infinite discussioni sento il bisogno di scrivere nel blog (un po' come scolpire nella pietra) quando è necessario chiamare Dispose.

Regola semplice:

  • Se una classe implementa IDisposable, se si crea e si usa un'istanza di tale classe alla fine bisogna chiamare Dispose

Regola più completa (le cose non sono mai così semplici):

  • Per ogni oggetto di una classe che implementa IDisposable è opportuno chiamare Dispose non appena l'oggetto non è più utilizzato
  • Il responsabile della chiamata a Dispose è l'owner dell'oggetto
  • L'owner iniziale di un oggetto è colui che lo crea, e normalmente rimane tale
  • In circostanze particolari l'ownership cambia; un caso comune è quello di una class factory, un caso meno tipico (ma che capita abitualmente) è quello di una struttura dati (es. una collection) in cui la struttura (o una classe che la contiene) diventa owner degli oggetti che terze parti (altri oggetti) allocano e vi inseriscono

Spiego un po' il motivo del post: diverse volte mi è stato riferito che per alcuni oggetti, che pur implementano IDisposable, non è necessario chiamare Dispose. Uno di questi, per esempio, è SqlCommand. A conforto di tale affermazione venivano portati codici di esempio trovati su MSDN e listati disassemblati con Reflector.

Sorry, non è così.

Se una classe implementa IDisposable, la Dispose va chiamata da qualcuno (sempre che si voglia scrivere del codice efficiente). La classe SqlCommand implementa IDisposable perché deriva da System.ComponentModel.Component, la quale definisce originariamente l'implementazione di IDisposable (che quindi viene ereditata da tutte le classi derivate). Purtroppo non esiste un modo per dire a una classe che IDisposable non è più necessaria ed è presente solo a causa di una classe base... insomma si potrebbe pensare a una ICancelDisposable per tale scopo, ma pensandoci bene non sarebbe una cosa sensata perché se la classe base in una versione successiva sfrutta diversamente IDisposable (e fa qualcosa in Dispose a differenza di quanto fa la classe Component) ecco che le classi derivate non potrebbero più esonerarsi dall'obbligo di seguire il pattern di utilizzo necessario.

E poi... indovinate un po'... con ADO.NET 2.0 ecco che la chiamata a Dispose su SqlCommand diventa necessaria!

All'interno di un assembly è "tollerabile" fare alcune assunzioni sulle classi che vi sono contenute, ma se si usa una classe contenuta in un assembly diverso direi che è d'obbligo seguire i pattern d'uso lasciando perdere vere o presunte ottimizzazioni. L'ottimizzazione è una cosa che si comincia a fare dopo aver fatto delle misure e le modifiche al codice restano solo se le misure successive all'ottimizzazione dimostrano un reale guadagno.

Nel 2005 le mail che mi chiederanno lumi in proposito avranno come risposta un link al mio blog!

powered by IMHO