2010-11-03 13 views
8

Quando ho letto alcuni articoli sulla gestione della memoria in C#, sono stato confuso dai metodi di Finalizer.Buoni esempi di utilizzo dei finalizzatori in C#

Ci sono così tante regole complicate che hanno a che fare con loro. Ad esempio, nessuno sa quando verranno chiamati i finalizzatori, CLR non garantisce che tutti i finalizzatori vengano richiamati quando i programmi si chiudono, ecc.

Per quali finalizzatori possono essere utilizzati in reale vita?

L'unico esempio che ho trovato è stato il programma che emette un segnale acustico all'avvio di GC.

Utilizzi Finalizzatori nel codice e potrebbero avere dei buoni campioni?

UPD:

finalizzatori può essere usato quando sviluppatori vogliono fare in modo che qualche classe sempre smaltito correttamente attraverso IDisposable. (link; Grazie Steve Townsend)

+4

Ho sempre scritto una manciata di finalizzatori negli ultimi 5 anni di progetti su cui ho lavorato e si trattava tutti di classi che interagivano con un'API legacy non gestita. In condizioni normali, i finalizzatori non sono mai stati effettivamente chiamati, perché gli oggetti sono stati eliminati prima che diventassero idonei per la garbage collection e la finalizzazione è stata soppressa esplicitamente. –

+0

@Dan Bryant - sì - non ho visto questo prima di rendere questo punto la mia risposta ... –

+1

Ho sempre pensato che i finalizzatori fossero lì per smaltire le risorse non gestite come un fail safe nel caso in cui IDisposable.Dispose() non venga chiamato (qualcuno ha dimenticato di usare using() o, infine), e non causa alcun problema se il tuo Dispose() chiama SuppressFinalize –

risposta

4

C'è una discussione esaustiva di utilizzo Finalizer, con esempi, here. Collegamento per gentile concessione di @SLaks a a related answer.

Vedere anche here per un riepilogo più conciso di quando ne avete bisogno (che è "non molto spesso").

C'è una bella risposta precedente here con un altro buon esempio del mondo reale.

In sintesi con un estratto pertinente:

finalizzatori sono necessari per garantire la rilascio di scarse risorse di nuovo nel il sistema operativo come handle di file, prese, oggetti kernel, ecc

Per ulteriori corretto esempi del mondo reale, cercare le classi interessate nel .Net Framework ricerca MSDN:

http://social.msdn.microsoft.com/Search/en-US?query=%22.Finalize%22&ac=8

Una valida ragione mi viene in mente quando si potrebbe essere necessario utilizzare un finalizzatore è se si avvolge un terzo codice nativo API in un wrapper gestito, e la libreria di codice API native di base richiede il rilascio tempestivo dei utilizzato le risorse del sistema operativo.

3

La migliore pratica a me nota è semplice non usarli. Potrebbero tuttavia esserci alcuni casi d'angolo quando si desidera utilizzare un finalizzatore, in particolare quando si gestiscono oggetti non gestiti e non è possibile implementare il modello Dispose (non conosco problemi legacy), quindi è possibile implementare il metodo Finalize con cautela (e potrebbe ridurre le prestazioni del tuo sistema, rendi i tuoi oggetti non morti e altri scenari potenzialmente strani, facendo attenzione alle eccezioni in quanto sono incatenabili :)).

Nel 99% dei casi basta scrivere il modello Dispose e utilizzare questo metodo per pulire da soli e tutto andrà bene.

+0

Non riesco a capire cosa stai dicendo qui (potresti voler formalizzare un po 'questo) ma sono sicuro al 100% che nel 99% dei casi non vuoi andare vicino ai finalizzatori. – annakata

+0

Questo è esattamente quello che sto dicendo. Potrei modificare la risposta, se non è chiara. I finalizzatori sono pericolosi e richiedono molta cautela quando li implementano. E come hanno detto i ragazzi prima di me, sono necessari solo quando si tratta di risorse non gestite. Ma l'interfacciamento con la tecnologia legacy o l'uso di alcune librerie c/C++ potrebbe sancire l'utilizzo. – luckyluke

+0

Una classe non dovrebbe quasi mai avere un finalizzatore a meno che lo scopo della classe non sia quello di avere uno (come nel caso di SafeHandle). Se un oggetto complicato richiederà l'uso esclusivo di qualcosa che sopravviverà, dovrebbe creare un altro oggetto il cui unico scopo è gestire quella cosa. Molte complicazioni sorgono se un oggetto con un finalizzatore contiene riferimenti ad altri oggetti, che possono a loro volta contenere riferimenti ad altri oggetti, ecc. È ironico che il pattern Dispose fornisca un supporto esplicito per fare in modo che una classe derivata aggiunga un finalizzatore - dubito che sia mai una buona idea. – supercat