La mise en œuvre de IDisposable sur une sous-classe lorsque le parent met également en œuvre IDisposable
J'ai un parent et un enfant de la classe que les deux ont besoin pour mettre en œuvre IDisposable
. Où dois - virtual
(et base.Dispose()
?) les appels entrent en jeu? Quand je viens de remplacer le Dispose(bool disposing)
appel, il se sent vraiment étrange disant que je n'en œuvre IDisposable
sans avoir explicite Dispose()
fonction (juste en utilisant l'héritage), mais ayant tout le reste.
Ce que j'avais fait (à banaliser un peu):
internal class FooBase : IDisposable
{
Socket baseSocket;
private void SendNormalShutdown() { }
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private bool _disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
SendNormalShutdown();
}
baseSocket.Close();
}
}
~FooBase()
{
Dispose(false);
}
}
internal class Foo : FooBase, IDisposable
{
Socket extraSocket;
private bool _disposed = false;
protected override void Dispose(bool disposing)
{
if (!_disposed)
{
extraSocket.Close();
}
base.Dispose(disposing);
}
~Foo()
{
Dispose(false);
}
}
- Msdn a publié des recommandations sur la façon de la sous-classe des objets de mise en œuvre de IDisposable.
Vous devez vous connecter pour publier un commentaire.
C'est quelque chose que vous ne devriez pas être concernés par.
Lorsque vous sous-classe d'une IDisposable classe, tout le "modèle dispose" la plomberie est déjà gérées par la classe de base. Vous devriez vraiment ne rien faire, mais remplacer le
protected Dispose(bool)
de la méthode et de vérifier si vous avez été éliminés déjà (pour bien éleverObjectDisposedException
.)Pour plus de détails, voir mon billet de blog sur Sous-classement à partir d'un IDisposable classe.
Aussi, souvent, c'est une bonne idée d'envisager l'encapsulation de l'IDisposable classe au lieu de sous-classement. Il ya des moments où un sous-classement IDisposable classe est approprié, mais ils sont assez rares. L'Encapsulation est souvent une meilleure solution.
Pourquoi compliquer les choses quand vous n'avez pas besoin de?
Puisque vous n'avez pas encapsuler toutes les ressources non managées, vous n'avez pas besoin de tout ça nettoie avec de finalisation. Et, vos classes sont à l'intérieur, ce qui suggère que vous avez le contrôle de la hiérarchie d'héritage au sein de votre assemblée.
Donc, l'compliqué approche serait:
Même si vous ne disposez pas des ressources non managées, je dirais que vous êtes beaucoup mieux les encapsulant dans leur propre classe jetables et de les utiliser comme vous l'auriez fait de toute autre jetables; aussi compliqué que le code ci-dessus.
L'idée de ce modèle est que vous remplacez le virtuel
Dispose
méthode, en appelantbase.Dispose
si nécessaire. La classe de base prend en charge le reste, l'appel de la virtuel méthode dispose (et donc de la mise en œuvre correcte). Le sous-classe ne devrait pas avoir besoin de mettre en œuvre égalementIDisposable
(c'estIDisposable
via l'héritage): IDisposable
, puisque c'est déjà héritant de l'interface. Je pense que je fais comme indiquant explicitement que "cette classe a des cédante qui se passe". Merci pour l'entrée, cependant. 🙂La classe enfant doit l'emporter sur le virtuel Disposer, effectuez l'une élimination spécifique à la sous-classe, et d'appeler la superclasse' en Disposer, ce qui à son tour fera de son propre travail.
EDIT: http://davybrion.com/blog/2008/06/disposing-of-the-idisposable-implementation/ est le modèle à suivre dans de tels cas. Pas le "Jetable" de la classe en particulier, mais de l'héritage et des remplacements.
J'ai toujours se tourner vers Joe Duffy étude très approfondie sur ce modèle. Pour moi, sa version de l'Évangile.
http://joeduffyblog.com/2005/04/08/dg-update-dispose-finalization-and-resource-management/
La première chose à retenir est que un finaliseur n'est pas nécessaire la plupart du temps. C'est pour l'effacement des ressources non managées où vous êtes de détenir directement des ressources autochtones, c'est à dire uniquement les ressources qui n'ont pas leur propre outil de finalisation.
Voici un exemple pour une base de classe sous-classe de la paire.
Noter que la sous-classe a sa propre _isDisposed membre. Notez également null-contrôle sur les ressources, puisque vous ne voulez pas des exceptions dans ces blocs.
Luc