Warum explizite Schnittstellenimplementierung verwenden eine geschützte Methode aufzurufen?
-
07-07-2019 - |
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?
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.
- 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
- 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
}
}