Frage

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

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

}

Gibt es einen guten Weg, um mit dieser Situation umzugehen, um sicherzustellen, dass identische Instanzen innerhalb der Klasse angerufen werden? (Es gibt kein Signal für Anrufer, die sie als "Schließen" aufrufen müssen, außer in Dokumentation.) Implementierungen von ImyInterface verkapeln nicht unbedingt identifizierbare Instanzen und werden während der gesamten Lebensdauer der Anwendung wiederholt geschlossen und wiederholt wiedereröffnet.

Ich denke darüber nach:

  • Implementieren Sie identifiziert in MyImplementation.
  • Set dispose (), um close () aufzurufen.
  • Fügen Sie einen Anruf zum Schließen () oder zu dem Beginn der Open hinzu, um sicherzustellen, dass der vorherige Anruf geschlossen wurde.

Benutzer von iMyInterface wissen nicht, welche Implementierung sie verwenden. Ich bin mir daher nicht sicher, wie viel Wertschöpfung MyImplementation Dispositable hat, und auch nicht, dass nicht alle Implementierungen idisposible -Werte zusammengefasst werden.

War es hilfreich?

Lösung

Zusätzlich zu den Antworten hier bereits:

Wenn diese Klasse (oft/manchmal) allein durch die Schnittstelle verwendet wird, würde ich Ihnen raten, Imyinterace von idisposable zu erben.

Dadurch können Ihre Benutzer diese Objekte konsistent verwenden. Der Nachteil ist natürlich, dass Sie möglicherweise (Dummy) Methoden zu Klassen hinzufügen müssen, die sie nicht benötigen. Aber der Vorteil ist in Konsistenz und Flexibilität: Was ist, wenn sich eine Klasse in Zukunft ändert, damit sie eine Entsorgung () benötigt?

Ein minimaler Ansatz:

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

}

Andere Tipps

Die Standardmethode, um dies zu bewältigen, besteht darin, einfach einfach zu haben MyImplementation implementieren IDisposable.

Wie John erwähnte, ist Ihr erster Aufzählungszeichen richtig.

Manchmal a Close() Methode ist funktionell gleichbedeutend mit Dispose(), und existiert, um die semantische Konsistenz mit einer Abstraktion aufrechtzuerhalten. Das heißt, a zu ergänzen a Open() Methode. Anderen Zeiten, Close() Ermöglicht es Ihnen, wieder zu öffnen, aber Dispose() sollte nicht. Ihr zweiter Kugelpunkt ist daher auch in Ordnung.

Der Kugelpunkt 3 ist nicht unbedingt anwendbar, da ein entsorgenes Objekt nicht wiederverwendet werden sollte. Wenn Sie anrufen müssen Open() Auch hier müssen Sie eine neue Instanz verwenden. In der Tat die Open() Methode sollte eine werfen ObjectDisposedException einmal Dispose() wurden gerufen (durch Überprüfung eines privaten disposed Boolesche Flagge). Wenn Sie möchten, dass das Objekt nach dem Schluss die Wiedereröffnung unterstützt, können Sie in Betracht ziehen, die Verwendung zu verwenden Debug.Assert() und/oder eine Ausnahme machen, wenn Open() wird ohne genannt Close(). Dies wird dazu beitragen, eine schlampige Behandlung dieser Fälle zu verhindern.

Befolgen Sie unbedingt das vollständige Einwegmuster, das mehr involviert ist, als einfach die Schnittstelle zu implementieren:

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;
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top