Warum kann eine eigene verschachtelte Klasse in C # nicht eine Klasse erweitern?

StackOverflow https://stackoverflow.com/questions/265585

  •  06-07-2019
  •  | 
  •  

Frage

Zum Beispiel:

public class A : A.B
{
    public class B { }
}

Welche diesen Fehler vom Compiler generiert:

  

Rund Basisklasse Abhängigkeit   Beteiligung 'A' und 'A. B'

ich eine verschachtelte Klasse immer gedacht, wie eine normale Klasse außer mit speziellen Regeln verhielten sich in Bezug auf die äußere Klasse private Mitglieder zugreifen, aber ich denke, es gibt einige implizite Vererbung zwischen den beiden Klassen auftreten?

War es hilfreich?

Lösung

Es gibt keine implizite Vererbung beteiligt, soweit ich das beurteilen kann. Ich würde dies in Ordnung zu erwarten haben -. Obwohl ich Seltsamkeit sich vorstellen kann, wenn A und B wurden generic

Es ist in Abschnitt 10.1.4 der Spezifikation:

  

Wenn eine Klasse B von einer Klasse A ableitet,   es ist ein für A Fehler bei der Kompilierung auf   auf B. hängen direkt A-Klasse hängt   auf seiner direkten Basisklasse (falls vorhanden) und    hängt direkt von der Klasse innerhalb   die es unmittelbar verschachtelt (wenn   irgendein). Angesichts dieser Definition ist die   vollständiger Satz von Klassen, auf denen ein   Klasse abhängt, ist die transitive   Schließung der direkt abhängig von   Beziehung.

Ich habe den entsprechenden Abschnitt hervorgehoben.

Das erklärt, warum die Compiler es ablehnen, aber nicht, warum die Sprache verbietet es. Ich frage mich, ob es eine CLI-Beschränkung ist ...

EDIT: Okay, ich habe eine Antwort von Eric Lippert hatte. Grundsätzlich wäre es technisch möglich sein (es gibt nichts in der CLI es zu verbieten), aber:

  • erlauben würde es in den Compiler, ungültig zu machen verschiedene gegenwärtige Annahmen um Bestellung und Zyklen schwierig sein
  • Es ist eine ziemlich seltsame Design-Entscheidung, die als zu Unterstützung leichter zu verbieten ist

Es wurde auch auf dem E-Mail-Thread festgestellt, dass es diese Art der Sache machen würde gültig:

A.B x = new A.B.B.B.B.B.B.B.B.B.B.B.B();

... aber das wäre schon (wie durch Tinister angegeben) gültig, wenn B von A abgeleitet.

Nesting + Vererbung = oddness ...

Andere Tipps

Dies ist kein C #, was so viel wie es eine Compiler Sache. Eine der Aufgaben eines Compilers ist eine Klasse im Speicher zu legen, dass eine Reihe von grundlegenden Datentypen ist, Zeiger, Funktionszeiger und anderer Klassen.

Es kann nicht das Layout für Klasse A konstruieren, bis er weiß, was das Layout der Klasse B ist. Es kann nicht wissen, was das Layout der Klasse B ist, bis es mit dem Layout der Klasse A. Rund Abhängigkeit abgeschlossen.

Ich denke, die Verschachtelung gemeint ist, um darzustellen, dass die verschachtelte Typ ist Teil der Definition der Verschachtelung Typ. Mit dieser Auslegung die Beschränkung Sinn zu der Zeit, da macht der Compiler die Definition von A trifft, wird A. B noch nicht definiert ist, und auch am Ende des A ist es bereits in Bezug auf A. B definiert ist.

In Bezug auf Fragen über das, was ich versuche, zu tun:

Im Grunde wollte ich eine Klasse erstellen, die mit sich selbst eine Komposition Beziehung hatte, aber ich wollte nicht das enthaltene Objekt haben, andere Objekte enthalten und schaffen somit eine Kette mit vielen „A hat-a A hat-a A hat-a A hat-a ...“Beziehungen. So war meine Gedanken zu der Zeit etwas tun, wie folgt aus:

public class A : A.AA
{
    public class AA
    {
        // All of the class's logic
    }

    private AA _containedObject;
}

die zu der Zeit schien ziemlich glatt, aber im Nachhinein bin ich nicht so sicher ...

Ich hatte über Google kramte und fanden keine gute Diskussion finden auf, so dachte ich, dass ich es hier posten würde.

Doch innerhalb der Kommentare eines Post an Eric Lippert Blog er Beispiele einer Klasse gibt eine verschachtelte Schnittstelle sowie eine Klasse eine generische Schnittstelle mit einer verschachtelten Klasse, die als Typargument Umsetzung Umsetzung (was nicht der Fall ist kompilieren und er im aktuellen Compiler ruft einen „Bug“). Diese beiden Beispiele betreffen Schnittstellen so dass ich mich gefragt, ob es einige spezielle Regeln mit verschachtelten Klassen war. Und es scheint, gibt es.

Ich war in der Lage, dies zu vermeiden (zumindest mit Schnittstellen) von einer separaten Klasse erbt die verschachtelten Schnittstellen enthält. (In meinem Szenario Ich bin auch Verweise auf diese Schnittstellen zurück.)

Statt:

public class MyClass<T1, T2, T3> :
   MyClass<T1, T2, T3>.Interface
where T1 : ...
where T2 : ... 
where T3 : ... {
   public interface Interface { Interface SomeMethod(); }

   Interface Interface.SomeMethod() {
      ...
   }
}

// compile error: Circular base class dependency

Sie etwas wie folgt aus:

public sealed class MyClassInterfaces<T1, T2, T3>
where T1 : ...
where T2 : ... 
where T3 : ... {
   public interface Interface { Interface SomeMethod(); }
}

sealed class MyClass<T1, T2, T3> :
   MyClassInterfaces<T1, T2, T3>.Interface
where T1 : ...
where T2 : ... 
where T3 : ... {
   MyClassInterfaces<T1, T2, T3>.Interface
   MyClassInterfaces<T1, T2, T3>.Interface.SomeMethod() {
      ...
   }
}

Um die Hässlichkeit mit expliziten Schnittstellenimplementierungen zu vermeiden, können Sie auch von der anderen Klasse erben, obwohl das nicht funktionieren würde, wenn Sie von einer geschachtelten Klasse zu erben versuchten, da sie nicht von beiden Klassen erben können.

public abstract class MyClassInterfaces<T1, T2, T3>
where T1 : ...
where T2 : ... 
where T3 : ... {
   public interface Interface { Interface SomeMethod(); }
}

sealed class MyClass<T1, T2, T3> :
   MyClassInterfaces<T1, T2, T3>,
   MyClassInterfaces<T1, T2, T3>.Interface
where T1 : ...
where T2 : ... 
where T3 : ... {
   Interface Interface.SomeMethod() {
      ...
   }
}

Das für mich keinen Sinn macht ... Sie versuchen, etwas zu erweitern, die nicht existiert !!! Klasse B besteht nur im Rahmen der Klasse A und aus diesem Grunde Ich denke, es ist eine Art der Vererbung.

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