Frage

Heute finde ich zufällig, dass eine C# -Klasse eine Schnittstelle sowohl auf implizit als auch explizit erben kann. Das überrascht mich. Wenn C# auf diese Weise funktioniert, kann sich eine Instanz anders verhalten, wenn sie auf unterschiedliche Weise verwiesen wird.

interface IFoo
{
    void DoSomething();
}

class Foo : IFoo
{
    #region IFoo Members
    public void DoSomething()
    {
        Console.WriteLine("do something implicitly");
    }
    #endregion

    #region IFoo Members
    void IFoo.DoSomething()
    {
        Console.WriteLine("do something explicitly");
    }
    #endregion
}


        Foo f = new Foo();
        f.DoSomething();

        ((IFoo)f).DoSomething();

Oben Code läuft und Ausgabe

do something implicitly
do something explicitly

Ich glaube, dass dieses Design von C# Inkonsistenz des Verhaltens darstellt. Vielleicht ist es obligatorisch, dass eine C# -Klasse implizit oder explizit von einer Schnittstelle erben kann, aber nicht beides.

Gibt es einen Grund, warum C# so gestaltet ist?

War es hilfreich?

Lösung

Ihr Beispiel tut nicht Impliziten und explizit IFOO implementieren. Sie implementieren nur explizit ifoo.dosometing (). Sie haben eine neue Methode in Ihrer Klasse namens dosomething (). Es hat nichts mit ifoo.dosomething zu tun, außer dass es denselben Namen und Parameter hat.

Andere Tipps

Jede Klasse, die eine Schnittstelle implementiert, hat eine Kartierung Zwischen den Mitgliedern dieser Klasse und den Mitgliedern der Schnittstelle. Wenn die Klasse ausdrücklich Implementiert ein Schnittstellenmitglied, dann wird die explizite Implementierung stets der Schnittstelle zugeordnet werden. Wenn es keine explizite Implementierung gibt, wird eine implizite Implementierung erwartet, und dieser wird der Schnittstelle zugeordnet.

Wenn eine Klasse denselben Mitgliedsnamen und zugehörigen Typen als Schnittstelle hat aber Es implementiert auch das entsprechende Mitglied für die Schnittstelle explizit und dann die "implizite" Implementierung der Klasse nicht als Implementierung der Schnittstelle betrachtet überhaupt (Es sei denn, die explizite Implementierung nennt es).

Zusätzlich zu unterschiedlichen Bedeutungen in jedem Fall, in dem die Klasse mehrere Schnittstellen mit demselben Elementnamen/-typen implementiert, auch mit nur einer Schnittstelle, die Klasse selbst Es wird als implizite Schnittstelle angesehen, die möglicherweise das gleiche Mitglied/Typen wie die einzige Schnittstelle aufweist, aber dennoch etwas anderes bedeutet.

Dies macht es flexibler für Kollisionen. Insbesondere schauen Sie sich an IEnumerator und IEnumerator<T> - beide haben eine Current Eigenschaft, aber von verschiedenen Typen. Du haben Um explizite Schnittstellenimplementierung zu verwenden, um sowohl zu implementieren (und die generische Form erweitert die nicht generische Form).

Multiple Vererbung: Was ist, wenn Sie von zwei Schnittstellen abgeleitet sind, die die gleiche Methode für verschiedene Zwecke definieren?

  interface IMoveable
  {
    public void Act();
  }

  interface IRollable
  {
    public void Act();
  }

  class Thing : IMoveable, IRollable
  {
    //TODO Roll/Move code here

    void IRollable.Act()
    {
      Roll();
    }

    void IMoveable.Act()
    {
      Move();
    }
  }

Leute, danke für deine Antworten.

Es stellt sich heraus, dass "C# -Klasse eine Schnittstelle sowohl implizit als auch explizit erbt" gleichzeitig "tatsächlich eine Illusion. Tatsächlich kann eine Klasse eine Schnittstelle für einmal erben.

In der ursprünglichen Frage erscheint die "Doomething" -Methode "implizit implementiert" -Kinschnittstellen -IFOO (die Methode wird tatsächlich von VS2008 generiert), ist es jedoch nicht. Mit explizite Implementierung von Schnittstellen -IFOO wird die "Doomething" -Methode nur eine normale Methode darstellt, die nichts mit Ifoo zu tun hat, außer mit derselben Signatur.

Ich glaube immer noch, dass es ein kniffliges Design von C#ist, und es ist leicht, es fälschlicherweise zu verwenden. Sagen Sie, ich habe einen solchen Code

        Foo f = new Foo();
        f.DoSomething();

Jetzt möchte ich es auf den folgenden Code neu umsetzen. Es scheint vollkommen in Ordnung, aber das Ausführungsergebnis ist anders.

        Action<IFoo> func = foo => foo.DoSomething();
        func(f);
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top