Frage

Ich implementierte vor kurzem eine Klasse wie:

class TestClass : IDisposable
{
    RegistryKey m_key;
    public TestClass()
    {
        m_key = Registry.CurrentUser.OpenSubKey("Software", false);
    }

    public void Dispose()
    {
        // m_key.Dispose();
        IDisposable disp = m_key;
        disp.Dispose();
    }
}

Wenn ich den direkten Aufruf Kommentar- Verfügungs, erhalte ich Fehler CS0117 ( „‚Microsoft.Win32.RegistryKey‘enthält keine Definition für‚entsorgen‘“). Einige Googeln führte mich href="http://bytes.com/groups/net-c/521478-interface-implementation" rel="noreferrer"> dieses Themas MSDN Dokumentation schlägt vor, dass der Autor würde es vorziehen, dass ich nenne Close () anstelle von Dispose (), aber nicht erklären, warum.

Was ist der Zweck dieses Musters (was ich denke, ich habe es in den IO-Klassen als auch zu sehen)? In Anbetracht der Tatsache, dass dies eine absichtliche Entscheidung der Klasse Autor war, wie schlecht ist der Code oben (der Aufruf der IDisposable-Schnittstelle zu entsorgen durch)? Es kann nicht so schlimm sein - schließlich ist es das, was in einer using-Anweisung geschehen würde, rechts

[Änderungen: 1) geändert Titel von "non-public" auf "explicit" 2) entfernt, um die explizite Implementierung von meinem Code versehentlich links in von Experimenten]

War es hilfreich?

Lösung

Das nennt man explizite Schnittstellenimplementierung . In Ihrem Beispiel, da Sie die Methode Dispose () als „ungültig IDisposable.Dispose ()“ definieren Sie die IDisposable-Schnittstelle als auch explizit zu implementieren.

Dies geschieht normalerweise um Kollisionen zu vermeiden. Wenn Microsoft jemals eine andere Methode Dispose () hinzufügen wollte, die etwas anderes zu RegistryKey täte, würde sie nicht in der Lage sein, wenn sie nicht explizit Umsetzung dieser Schnittstelle verwendet.

Dies geschieht oft mit dem generischen IEnumerable Schnittstelle. Es erfordert, dass Sie auch den nicht-generischen Schnittstelle IEnumerable zu implementieren. Das einzige Mitglied in diesen beiden Schnittstellen ist GetEnumerator, mit dem generischen einem nützlichen zu sein, so dass sie in der Regel wie folgt umgesetzt:

public clas SomeClass : IEnumerable<SomeOtherClass>
{
    public IEnumerator<SomeOtherClass> GetEnumerator ()
    {
        ...
    }

    IEnumerator IEnumerable.GetEnumerator ()
    {
        return GetEnumerator ();
    }
}

Auf diese Weise, wenn Sie ein Objekt von Someclass des GetEnumator Methode aufrufen, ruft die generische Version, da die andere ausdrücklich umgesetzt wurde, so dass wir die starken eingeben Generika bekommen können.

Siehe Seiten 166-169 von Programmierung C # von Jesse Liberty (ich die vierte Ausgabe haben).

Andere Tipps

Die meisten Menschen mit mir nicht einverstanden ist, aber Ich mag mit expliziter Schnittstellenimplementierung für alle Schnittstellen . Ich möchte klarstellen, ob ich eine Methode Schreiben auf mein Objekt oder auf meine Schnittstelle aufgerufen werden.

Das ist schmerzhaft, wenn Sie einen Verweis auf das Objekt und wollen eine Schnittstelle Methode aufzurufen (wie im obigen Beispiel), aber ich mildere sie durch Schreiben:

class C : IDisposable
{
    public IDisposable IDisposable { get { return this; } }
    void IDisposable.Dispose() { }
}

was bedeutet, dass die Methode auf C Aufruf wie folgt aussieht:

C c = ...
c.IDisposable.Dispose();

Der Compiler parst dies als „Rufen Sie die IDisposable Eigenschaft auf C, dann rufen Sie die Dispose() Methode auf das Ergebnis“ aber ich lese es als „Rufen Sie die IDisposable.Dispose() Methode auf C“, die hier natürlich erscheint.

Dieser Ansatz kann hässlich, wenn generische Schnittstellen, leider.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top