Domanda

In Visual Studio, quando digito la riga " Implementa IDisposable " ;, l'IDE aggiunge automaticamente:

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

Dispose () deve essere lasciato da solo e il codice di pulizia deve essere inserito in Dispose (smaltimento) .

Tuttavia Dispose Finalize Pattern dice che dovresti anche scavalcare Sub Finalize () per chiamare Dispose (False) . Perché l'IDE non aggiunge anche questo? Devo aggiungerlo da solo o è in qualche modo chiamato implicitamente?

EDIT: Hai idea del perché l'IDE aggiunge automaticamente l'80% delle cose richieste ma lascia fuori il metodo Finalize? Il punto centrale di questo tipo di funzionalità non è aiutarti a non dimenticare queste cose?

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

È stato utile?

Soluzione

Se in realtà stai trattenendo risorse non gestite che non verranno automaticamente ripulite dal garbage collector e ripulite quelle nel tuo Dispose (), allora sì, dovresti fare lo stesso in Finalize ().

Se stai implementando IDisposable per qualche altro motivo, l'implementazione di Finalize () non è richiesta.

La domanda di base è questa: se non si chiamasse Dispose () e si raccolesse la spazzatura dell'oggetto, si perderebbe la memoria? Se sì, implementa Finalize. Se no, non è necessario. Inoltre, evita di implementare Finalize "solo perché è più sicuro". Gli oggetti con finalizzatori personalizzati possono potenzialmente necessitare di due passaggi GC per liberarli: una volta per metterli nella coda dei finalizzatori in sospeso e un secondo passaggio per liberare effettivamente la memoria.

Altri suggerimenti

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

Nella maggior parte dei casi il motivo per cui una classe è usa e getta è perché mantiene i riferimenti ad altri oggetti IDisposable gestiti. In questo caso, nessun metodo Finalize è necessario o auspicabile.

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

Come altri hanno già detto, non è necessario implementare un finalizzatore a meno che non si disponga 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 un post di blog abbastanza lungo che copre lo sfondo e l'implementazione di IDisposable e finalizzatori qualche tempo fa, il che potrebbe valere la pena di essere letto se non ne sei del tutto chiaro.

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