Frage

Beim Surfen Quelle ASP.NET MVC Code in codeplex , fand ich es üblich ist, eine Klasse explizit Implementierung Schnittstelle zu haben. Die explizit implementiert Methode / Eigenschaft rufen Sie dann eine andere „geschützte virtuelle“ Methode / Eigenschaft mit dem gleichen Namen.

Beispiel:

public class MvcHandler : IHttpHandler, IRequiresSessionState 
{
    protected virtual bool IsReusable 
    {
        get 
        {
           return false;
        }
    }

    bool IHttpHandler.IsReusable 
    {
        get 
        {
           return IsReusable;
        }
    }
}

Ich bin jetzt sicher, was der Vorteil dieser Art der Programmierung ist. Für mich, ziehe ich es nur implizit die Schnittstelle IHttpHandler zu implementieren.

Ich denke, der Autor gerade nicht wollen, MvcHandler hat eine öffentliche Eigenschaft IsResuable . Die Eigenschaft IsReusable kann nur, wenn Instanz von verwendet werden MvcHandler als behandelt wird IHttpHandler . Trotzdem bin ich mir nicht sicher, warum der Autor, was auf diese Weise.

Wer mehr Vorteile über diese Art von Interface-Implementierung wissen?

War es hilfreich?

Lösung

Nun, nicht spezifisch für MVC, aber dieser Ansatz ermöglicht es Ihnen, hält den Kern öffentlichen API sauber . Es ist auch sinnvoll, wenn es überhaupt ein Risiko von unterschiedlichen Schnittstellen ist / etc mit dem gleichen Namen und Unterschrift, aber andere Bedeutung. In Wirklichkeit ist dies selten.

Sie können damit auch eine Implementierung zur Verfügung zu stellen, wo Sie den Rückgabetyp wollen in Subklassen ändern:

(ICloneable der Einfachheit halber gewählt - werden nicht auf der Tatsache, aufgehängt, dass es sich um eine schlecht definierte Schnittstelle ist ... ein besseres Beispiel gewesen wäre, Dinge wie DbCommand usw., die das tun - aber das ist schwieriger zu zeigen in ein kurzes Beispiel)

class Foo : ICloneable
{
    public Foo Clone() { return CloneCore(); }
    object ICloneable.Clone() { return CloneCore(); }
    protected virtual Foo CloneCore() { ... }
}

class Bar : Foo
{
    protected override Foo CloneCore() { ... }
    public new Bar Clone() { return (Bar)CloneCore(); }
}

Wenn wir eine öffentliche virtuelle Methode verwendet hätten, haben wir nicht in der Lage sein, es override und Verwendung new in der Basisklasse, wie es nicht erlaubt ist, beides zu tun:

class A
{
    public virtual A SomeMethod() { ... }
}
class B : A
{
    public override A SomeMethod() { ... }
    //Error 1   Type 'B' already defines a member called 'SomeMethod' with the same parameter types
    public new B SomeMethod() { ... }
}

, um den geschützten virtuellen Ansatz, jede Nutzung:

  • Foo.Clone ()
  • Bar.Clone ()
  • ICloneable.Clone ()

verwenden alle die richtige CloneCore() Implementierung für die konkrete Art.

Andere Tipps

Wenn eine Klasse implementiert IFoo.Bar explizit, und eine abgeleitete Klasse muss IFoo.Bar, etwas anderes zu tun, wird es keine Möglichkeit für die abgeleitete Klasse die Basis-Klasse Implementierung dieser Methode aufzurufen. Eine abgeleitete Klasse, die nicht IFoo.Bar neu implementieren könnte die Basis-Klasse Implementierung über ((IFoo)this).Bar() nennen, aber wenn die abgeleitete Klasse Wieder implementiert IFoo.Bar (wie es um sein Verhalten haben würde zu ändern) die zuvor erwähnte Aufruf der abgeleiteten würde -Klasse Neuimplementierung, anstatt die Basisklasse Implementierung. Auch würde ((IFoo)(BaseType)this).bar nicht helfen, einen Verweis auf einen Interface-Typen, da Gießen wird keine Informationen über die Art der Referenz verwerfen (in Bezug auf die Art der Instanz Instanz gegen), die gegossen wurde.

Nachdem eine explizite Schnittstellenimplementierung nichts tun, sondern rufen Sie eine geschützte Methode, um dieses Problem vermeidet, da eine abgeleitete Klasse das Verhalten der Schnittstellenmethode ändern können, indem die virtuelle Methode überschrieben, unter Beibehaltung der Fähigkeit die Basisimplementierung zu nennen, wie es für richtig hält . IMHO, C # sollte eine explizite Schnittstellenimplementierung eine virtuelle Methode mit einem CLS-kompatibelen Namen produziert gehabt haben, so jemand in C # ein Derivat einer Klasse zu schreiben, die IFoo.Bar explizit umgesetzt könnte override void IFoo.Bar sagen, und jemand in einer anderen Sprache zu schreiben könnte sagen, z.B. Overrides Sub Explicit_IFoo_Bar(); da jede abgeleitete Klasse kann IFoo.Bar neu implementieren, und da jede abgeleitete Klasse, die IFoo.Bar nicht neu implementieren kann sie sich selbst nennen, sehe ich nicht, dass es die explizite Implementierung jeder nützlichen Zweck ist versiegelt werden müssen.

Im übrigen in vb.net, würde das normale Muster einfach ohne Notwendigkeit für eine separate virtuelle Methode Protected Overridable Sub IFoo_Bar() Implements IFoo.Bar werden.

  1. Wenn ein Mitglied explizit implementiert ist, kann es nicht durch eine Instanz der Klasse zugegriffen werden, sondern nur über eine Instanz der Schnittstelle. Referenz: Explizite Schnittstellenimplementierung Tutorial
  2. Wie meine Erfahrung, wenn Schnittstelle Implementierer explizit eine Schnittstelle implementieren er Compiler-Fehler erhalten, nachdem Sie eine Methode aus Drop-Schnittstelle, während er nicht benachrichtigt wird, wenn er / sie es implizit umzusetzen und das Verfahren wird im Code bleiben.

Probe für Grund 1:

public interface IFoo
{
    void method1();
    void method2();
}

public class Foo : IFoo
{
    // you can't declare explicit implemented method as public
    void IFoo.method1() 
    {
    }

    public void method2()
    {
    }

    private void test()
    {
        var foo = new Foo();
        foo.method1(); //ERROR: not accessible because foo is object instance
        method1(); //ERROR: not accessible because foo is object instance
        foo.method2(); //OK
        method2(); //OK

        IFoo ifoo = new Foo();
        ifoo.method1(); //OK, because ifoo declared as interface
        ifoo.method2(); //OK
    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top