Question

interface IMyInterace
{
void Open();
object Read();
void Close();
}

class MyImplementation : IMyInterface
{
public void Open() { /* instantiates disposible class */ }
//...
public void Close() { /* calls .Dispose(); */ }

}

Y at-il une bonne façon de traiter ce type de situation pour faire en sorte que les instances disposible à l'intérieur de la classe appelée? (Il n'y a pas de signal aux appelants qu'ils doivent appeler « Fermer », sauf dans la documentation.) Implémentations de IMyInterface ne cas pas nécessairement encapsulent IDisposible et sont fermées et réouvertes à plusieurs reprises tout au long de la durée de vie de l'application.

Je pense à faire ceci:

  • Mettre en œuvre IDisposible dans MyImplementation.
  • Set Dispose () pour appeler Close ().
  • Ajouter un appel à Close () ou Dispose () à la Début de Ouvert à assurer précédente appel a été fermé.

Les utilisateurs de IMyInterface ne sais pas ce que la mise en œuvre qu'ils utilisent, donc je ne suis pas sûr combien de valeur faire MyImplementation a disposible, et encore, pas toutes les implémentations symboliseront IDisposibles.

Était-ce utile?

La solution

En plus des réponses déjà ici:

Si cette classe est (souvent / parfois) utilisé par l'interface seul, je vous conseille de IMyInterace Hériter de IDisposable.

Cela permettra à vos utilisateurs d'utiliser ces objets de manière cohérente. L'inconvénient est bien sûr que vous devrez peut-être ajouter (factices) méthodes Dispose aux classes qui ne doivent pas réellement. Mais l'avantage est en cohérence et la flexibilité: si une classe change à l'avenir afin qu'il a besoin d'un Dispose ()

?

Une approche minimale:

interface IMyInterace : IDisposable { }

sealed class MyImplementation : IMyInterface 
{   
   public void Open() { /* instantiates disposible class */ }

   public void Close() { /* calls _myField.Dispose(); */ }

   public void Dispose() { Close(); }  // only use this short form in a sealed class

}

Autres conseils

La méthode standard pour gérer cela est d'avoir simplement MyImplementation mettre en œuvre IDisposable.

Comme mentionné John, votre premier point est à droite sur.

Parfois, une méthode de Close() est fonctionnellement synonyme de Dispose() et existe pour maintenir la cohérence sémantique avec une abstraction. C'est, pour compléter une méthode Open(). D'autres fois, Close() vous permettra de rouvrir, mais Dispose() ne devraient pas. Votre deuxième puce point est donc bien, ainsi.

point Bullet 3 est pas nécessairement applicable, car un objet disposé ne doit pas être réutilisé. Si vous devez appeler Open() à nouveau, vous devez utiliser une nouvelle instance. En fait, la méthode de Open() devrait lancer une ObjectDisposedException fois Dispose() ont été appelés (en cochant un drapeau booléen disposed privé). Si vous voulez que l'objet à l'appui réouverture après la fermeture, vous pouvez envisager d'utiliser Debug.Assert() et / ou de lancer une exception si Open() est appelée sans Close(). Cela aidera à prévenir la gestion bâclée de ces instances.

Assurez-vous de suivre le modèle jetable complet, qui est plus impliqué que la mise en œuvre simplement l'interface:

bool disposed;

public void Dispose() // don't make virtual!
{
    Dispose(true);
    GC.SuppressFinalize(this);
}

protected virtual void Dispose(bool disposing)
{
    if(!disposed)
    {
        if(disposing) 
        {
            // dispose of managed resources here, for example:
            // if(resource != null) { resource.Dispose(); } 
        }
    }

    // dispose of unmanaged resources here 

    disposed = true;
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top