Je ne me souviens jamais de toutes les règles d'implémentation de l'interface IDisposable, j'ai donc essayé de créer une classe de base qui s'occupe de tout cela et qui rend l'IDisposable facile à implémenter. Je voulais juste entendre votre opinion si cette implémentation est correcte telle quelle ou si vous voyez quelque chose que je pourrais améliorer. L'utilisateur de cette classe de base est supposé en dériver, puis implémenter les deux méthodes abstraites ReleaseManagedResources()
et ReleaseUnmanagedResources()
. Donc, voici le code:Cette implémentation IDisposable est-elle correcte?
public abstract class Disposable : IDisposable
{
private bool _isDisposed;
private readonly object _disposeLock = new object();
/// <summary>
/// called by users of this class to free managed and unmanaged resources
/// </summary>
public void Dispose() {
DisposeManagedAndUnmanagedResources();
}
/// <summary>
/// finalizer is called by garbage collector to free unmanaged resources
/// </summary>
~Disposable() { //finalizer of derived class will automatically call it's base finalizer
DisposeUnmanagedResources();
}
private void DisposeManagedAndUnmanagedResources() {
lock (_disposeLock) //make thread-safe
if (!_isDisposed) { //make sure only called once
try { //suppress exceptions
ReleaseManagedResources();
ReleaseUnmanagedResources();
}
finally {
GC.SuppressFinalize(this); //remove from finalization queue since cleaup already done, so it's not necessary the garbage collector to call Finalize() anymore
_isDisposed = true;
}
}
}
private void DisposeUnmanagedResources() {
lock (_disposeLock) //make thread-safe since at least the finalizer runs in a different thread
if (!_isDisposed) { //make sure only called once
try { //suppress exceptions
ReleaseUnmanagedResources();
}
finally {
_isDisposed = true;
}
}
}
protected abstract void ReleaseManagedResources();
protected abstract void ReleaseUnmanagedResources();
}
Merci Joe, oui je vais prendre la serrure dans le finaliseur. –
Non, il ne peut pas avoir été collecté, car le jetable actuel contient une référence à celui-ci. –
"Non, cela n'a pas pu être collecté" - c'est faux. Il peut avoir été collecté - à partir de MSDN: "Les finaliseurs de deux objets ne sont pas forcément exécutés dans un ordre spécifique, même si un objet se réfère à l'autre, si l'objet A a une référence à l'objet B , L'objet B peut déjà avoir été finalisé lorsque le finaliseur de l'objet A démarre. "(Voir http://msdn.microsoft.com/en-us/library/system.object.finalize.aspx) – Joe