2009-04-20 12 views
7

Ho programmato in .NET per quattro anni (principalmente C#) e utilizzo estensivamente IDiposable, ma devo ancora trovare la necessità di un finalizzatore. Per cosa sono finalisti?Per cosa servono i finalizzatori?

+5

Btw, sono inglese e ho scoperto che è una * veramente * * davvero * buona idea prendere l'abitudine di scrivere "finalizza" e "inizializzare" con una z, non con una s. Altrimenti, non puoi mai trovare le cose insanguinate quando le cerchi nella documentazione! –

+1

@onebyone - idem. Allo stesso modo, Colour ... mi causava irritazione, ma ora considero solo il termine tecnico per l'industria, e ho finito il lavoro ;-p –

+0

Ho cercato di allenarmi - lo uso in documentazione e in pubblico di fronte al codice, ma non riesco proprio a portarmi a farlo nella "vita reale". –

risposta

10

Un finalizzatore è un ultimo tentativo per assicurare che qualcosa venga pulito correttamente e di solito è riservato agli oggetti che contengono risorse non gestite non gestite, come handle non gestiti, ecc. Che non verranno raccolti.

È davvero raro scrivere un finalizzatore. Fortunatamente (e diversamente da IDisposable), i finalizzatori non devono essere propagati; quindi se hai un ClassA con un finalizzatore e un ClassB che include ClassA, allora ClassB non ha bisogno di un finalizzatore - ma molto probabilmente entrambi ClassA e ClassB implementerebbero IDisposable.

Per il codice gestito, IDisposable è in genere sufficiente. Anche se non si pulisce correttamente, alla fine gli oggetti gestiti verranno raccolti (supponendo che vengano rilasciati).

1

I finalizzatori servono a ripulire le risorse se non sono state smaltite.

IE, nulla consente di chiamare Dispose(), ma i finalizzatori vengono chiamati automaticamente dal garbage collector.

Questa funzionalità non dovrebbe essere invocata, in quanto non vi è alcuna garanzia quando (o se) la garbage collection arriverà al proprio oggetto.

2

I finalizzatori sono intesi come un meccanismo per liberare risorse non controllate dal garbage collector, come un handle non gestito. Mentre Dispose potrebbe farlo, non è garantito che il consumatore lo chiamerà.

4

I finalizzatori sono solo per la liberazione delle risorse non gestite come le maniglie bitmap GDI, ad esempio. Se non si assegnano risorse non gestite, non sono necessari i finalizzatori. In generale è una cattiva idea quella di toccare qualsiasi oggetto gestito in un finalizzatore perché l'ordine di finalizzazione non è garantito.

Un'altra tecnica utile che utilizza un finalizzatore è di affermare che Dispose è stato chiamato quando l'applicazione è richiesta per farlo. Questo può aiutare cattura errori di codifica in una build di debug:

void Dispose() 
{ 
    GC.SuppressFinalize(this); 
} 
#if DEBUG 
~MyClass() 
{ 
    Debug.Fail("Dispose was not called."); 
} 
#endif 
1

Wikipedia says:

... un finalizzatore è un pezzo di codice che assicura che alcune azioni necessarie sono prese quando un acquisito risorsa ... non viene più utilizzato [perché l'oggetto possedere è stato garbage raccolte]

E se non stai usando un finalizzatore mentre scrivi IDisposables hai probabilmente perdite di memoria, perché non c'è alcuna garanzia che un proprietario chiamerà Dispose().

MS si consiglia si scrive qualcosa di simile a questo nella vostra implementatori:

public void Dispose() 
    { 
     this.Dispose(true); 
    } 

    protected virtual void Dispose(bool disposing) 
    { 
     if (!this.isDisposed) 
     { 
      if (disposing) 
      { 
       GC.SuppressFinalize(this); 
      } 
     } 
     //Dispose of resources here 
     this.isDisposed = true; 
    } 

    ~DisposableSafe() 
    { 
     this.Dispose(false); 
    } 

    private bool isDisposed = false; 

Personalmente, non riesco a sopportare il copia-incolla quindi tendo ad avvolgere che in una classe astratta per il riutilizzo.

+0

A meno che la tua classe non si occupi direttamente delle risorse * non gestite *, probabilmente non hai bisogno di un finalizzatore. Le risorse gestite devono essere gestite dal GC, indipendentemente dal fatto che l'utente chiami o meno Dispose. – LukeH

+0

Questo mi ha fatto scrivere "possibilmente" invece di "probabilmente" e mi preoccupavo di ciò. Ma non è del tutto vero comunque. Se la tua classe implementa qualche altro IDisposable, allora hai la responsabilità di chiamare Dispose() anche su questo. E così via, da MSDN "L'uso principale di questa interfaccia è quello di rilasciare risorse non gestite." – annakata

Problemi correlati