Domanda

Se .NET dispone di Garbage Collection, perché è necessario chiamare esplicitamente IDisposable ?

È stato utile?

Soluzione

La garbage collection è per la memoria. È necessario disporre di risorse non di memoria: handle di file, socket, handle GDI +, connessioni al database, ecc. Questo è in genere ciò che sta alla base di un tipo IDisposable , sebbene l'handle effettivo possa essere molto più lungo di una catena di riferimenti. Ad esempio, potresti Dispose un XmlWriter che dispone di un StreamWriter a cui ha un riferimento, che dispone di FileStream esso ha un riferimento a, che rilascia l'handle del file stesso.

Altri suggerimenti

Espandendo un po 'gli altri commenti:

Il metodo Dispose () dovrebbe essere chiamato su tutti gli oggetti che hanno riferimenti a risorse non gestite. Esempi di questo includono stream di file, connessioni al database, ecc. Una regola di base che funziona la maggior parte delle volte è: " se l'oggetto .NET implementa IDisposable, dovresti chiamare Dispose () quando hai finito con l'oggetto.

Tuttavia, alcune altre cose da tenere a mente:

  • La chiamata a dispose non ti dà il controllo su quando l'oggetto viene effettivamente distrutto e la memoria rilasciata. GC lo gestisce per noi e lo fa meglio di noi.
  • Dispose pulisce tutte le risorse native, in fondo alla pila di classi base come indicato da Jon. Quindi chiama SuppressFinalize () per indicare che l'oggetto è pronto per essere recuperato e non è necessario ulteriore lavoro. La prossima esecuzione del GC lo pulirà.
  • Se non viene chiamato Dispose, GC trova l'oggetto come da pulire, ma Finalize deve essere chiamato per primo, per assicurarsi che le risorse vengano rilasciate, che la richiesta per Finalize sia messa in coda e il GC si avvii, quindi il GC la mancanza di una chiamata a Dispose impone l'esecuzione di un altro GC prima che l'oggetto possa essere pulito. Questo fa sì che l'oggetto venga promosso alla successiva "generazione" di GC. Questo potrebbe non sembrare un grosso problema, ma in un'applicazione a pressione ridotta, la promozione di oggetti fino a generazioni più elevate di GC può spingere un'applicazione ad alta memoria oltre il muro a diventare memoria esaurita.
  • Non implementare IDisposable nei propri oggetti a meno che non sia assolutamente necessario. Le implementazioni inadeguate o inutili possono effettivamente peggiorare le cose anziché migliorarle. Una buona guida può essere trovata qui:

    Implementazione di un metodo di smaltimento

    Oppure leggi l'intera sezione di MSDN su Garbage Collection

Perché a volte gli oggetti contengono risorse accanto alla memoria. GC rilascia la memoria; IDisposable è così puoi rilasciare qualsiasi altra cosa.

perché vuoi controllare quando verranno ripulite le risorse trattenute dal tuo oggetto.

Vedi, GC funziona, ma lo fa quando ne ha voglia e anche in questo caso, i finalizzatori che aggiungi ai tuoi oggetti verranno chiamati solo dopo 2 raccolte GC. A volte, vuoi ripulire immediatamente quegli oggetti.

Questo è quando si utilizza IDisposable. Chiamando Dispose () esplicitamente (o usando lo zucchero sintattico di un blocco using) puoi ottenere l'accesso al tuo oggetto per ripulire se stesso in modo standard (cioè potresti aver implementato la tua chiamata cleanup () e chiamarla esplicitamente invece)

Esempi di risorse che si desidera ripulire immediatamente sono: handle di database, handle di file, handle di rete.

Per usare la parola chiave using l'oggetto deve implementare IDisposable. http://msdn.microsoft.com/en-us /library/yh598w02(VS.71).aspx

L'interfaccia IDisposable viene spesso descritta in termini di risorse, ma la maggior parte di tali descrizioni non considera realmente ciò che "risorse". significa davvero.

Alcuni oggetti devono chiedere alle entità esterne di fare qualcosa per loro, a scapito di altre entità, fino a nuovo avviso. Ad esempio, un oggetto che comprende un flusso di file potrebbe dover chiedere a un file system (che può trovarsi in qualsiasi parte dell'universo connesso) di concedere l'accesso esclusivo a un file. In molti casi, il bisogno dell'oggetto per l'entità esterna sarà legato al bisogno del codice esterno per l'oggetto. Una volta che il codice client ha fatto tutto ciò che avrà a che fare con il suddetto oggetto flusso di file, ad esempio, quell'oggetto non avrà più bisogno di avere accesso esclusivo (o qualsiasi accesso per quella materia) al suo file associato.

In generale, un oggetto X che chiede a un'entità di fare qualcosa fino a nuovo avviso comporta l'obbligo di fornire tale avviso, ma non può fornire tale avviso fintanto che il cliente di X potrebbe aver bisogno dei servizi di X. Lo scopo di IDisposable è di fornire un modo uniforme per far sapere agli oggetti che i loro servizi non saranno più richiesti, in modo che possano avvisare le entità (se presenti) che agiscono per loro conto che i loro servizi non sono più richiesti. Il codice che chiama IDisposable non ha bisogno né di sapere né di preoccuparsi di quali (se ve ne sono) servizi che un oggetto ha richiesto da entità esterne, poiché IDisposable invita semplicemente un oggetto a soddisfare gli obblighi (se qualsiasi) a entità esterne.

Per mettere le cose in termini di "risorse", un oggetto acquisisce una risorsa quando chiede a un'entità esterna di fare qualcosa per suo conto (in genere, sebbene non necessariamente, concedendo un uso esclusivo di qualcosa) fino a nuovo avviso e rilascia una risorsa quando indica che l'entità esterna non è più richiesta dai suoi servizi. Il codice che acquisisce una risorsa non guadagna un "oggetto" tanto quanto comporta un obbligo; il rilascio di una risorsa non rinuncia a una "cosa", ma soddisfa invece un obbligo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top