2008-09-22 11 views
5

In Visual Studio, quando digito la linea "Implements IDisposable", l'IDE aggiunge automaticamente:VB.NET - È necessario aggiungere un metodo Finalize durante l'implementazione di IDisposable?

  • una variabile disposedValue membro
  • un Sub Dispose() Implements IDisposable.Dispose
  • un Sub Dispose(ByVal disposing As Boolean)

Il Dispose() dovrebbe essere lasciato da solo, e il codice di pulizia dovrebbe essere messo in Dispose(disposing).

Tuttavia, il Dispose Finalize Pattern indica che è necessario ignorare anche Sub Finalize() per chiamare Dispose(False). Perché l'IDE non aggiunge anche questo? Devo aggiungerlo io stesso, o è in qualche modo chiamato implicitamente?

EDIT: Qualsiasi idea del perché l'IDE aggiunge automaticamente l'80% delle cose necessarie, ma lascia fuori il metodo Finalize? Non è il punto centrale di questo tipo di funzionalità che ti aiuta a non dimenticare queste cose?

EDIT2: Grazie a tutti per le vostre risposte eccellenti, questo ora ha perfettamente senso!

risposta

11

Se in realtà si detengono risorse non gestite che non verranno automaticamente ripulite dal garbage collector e pulite quelle in Dispose(), allora sì, si dovrebbe fare lo stesso in Finalize().

Se si implementa IDisposable per qualche altra ragione, l'implementazione di Finalize() non è richiesta.

La domanda di base è questa: se Dispose() non è stato chiamato e la garbage collection dell'oggetto raccolto, la perdita di memoria? Se sì, attuare Finalize. Se no, non è necessario. Inoltre, evita di implementare Finalize "solo perché è più sicuro". Gli oggetti con finalizzatori personalizzati possono potenzialmente avere bisogno di due passaggi GC per liberarli - una volta per metterli nella coda dei finalizzatori in attesa e un secondo passaggio per liberare effettivamente la loro memoria.

+1

L'implementazione di Dispose non significa che è necessario implementare anche un finalizzatore. È possibile liberare risorse non gestite in un metodo Dispose senza mai aver bisogno di un finalizzatore. Se è necessario implementare un finalizzatore, la logica di pulitura effettiva dovrebbe essere in una funzione separata che consente di disporre e finalizzare la chiamata. –

+1

Questo è sbagliato.Se si fa affidamento esclusivamente su Dispose() per liberare risorse non gestite, la memoria si perde nei casi in cui Dispose non viene chiamato. Questo è esattamente ciò che il finalizzatore è lì per. – Laurent

+1

Non sono sicuro del motivo per cui non ho risposto al commento di Scott prima - non l'ho notato, ma Laurent ha ragione - se il tuo Dispose sta pulendo le risorse non gestite, è necessario un Finalize per sicurezza. Non lasciarlo perché sei pigro. –

3

No, non è necessario disporre di Finalizzazione a meno che non si disponga di risorse non gestite per la pulizia.

Nella maggior parte dei casi, la ragione per cui una classe è disponibile è perché mantiene i riferimenti ad altri oggetti IDisposable gestiti. In questo caso nessun metodo Finalize è necessario o desiderabile.

+0

È possibile liberare risorse non gestite in un metodo Dispose senza mai aver bisogno di un finalizzatore. –

+0

È possibile, ma se Dispose non viene chiamato, probabilmente si perde anche la memoria senza un metodo Finalize. –

1

Come altri hanno già detto, non è necessario implementare un finalizzatore a meno che non si tratti direttamente di risorse non gestite. Inoltre, supponendo che tu stia lavorando in .NET 2.0 o versioni successive, è improbabile che tu abbia mai bisogno di implementare un finalizzatore perché in genere SafeHandle può essere utilizzato per racchiudere le risorse non gestite.

Ho scritto uno fairly long blog post che copre lo sfondo e l'implementazione di IDisposable e finalizzatori un po 'indietro, che può essere la pena una lettura se non si è completamente chiari su di esso.

+0

È possibile liberare risorse non gestite in un metodo Dispose senza mai aver bisogno di un finalizzatore. –

+0

Beh sì, questo è il punto centrale del modello IDisposable. Tuttavia, se la gente dimentica di chiamare Dispose, il finalizzatore è una protezione che li pulisce alla fine, che non può essere dimenticato perché viene chiamato dal runtime. –

2
Implements IDisposable 

Public Overloads Sub Dispose() Implements IDisposable.Dispose 

    Dispose(True) 
    GC.SuppressFinalize(Me) 

End Sub 

Protected Overloads Sub Dispose(ByVal disposing As Boolean) 

    If disposing Then 
     ' Free other state (managed objects). 
    End If 
    ' Free your own state (unmanaged objects). 
    ' Set large fields to null. 
End Sub 

Protected Overrides Sub Finalize() 

    Dispose(False) 
    MyBase.Finalize() 

End Sub 
+3

Una singola lastra di codice non è molto utile. Cerca di essere più costruttivo, con una piccola descrizione e ragionamento dietro il codice fornito. –