32 votes

Pourquoi une classe ne peut-elle pas étendre sa propre classe imbriquée en C #?

Par exemple:

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

Ce qui génère cette erreur à partir du compilateur:

Dépendance de classe de base circulaire impliquant «A» et «A.B»

J'ai toujours pensé qu'une classe imbriquée se comportait exactement comme une classe régulière, sauf avec des règles spéciales concernant l'accès aux membres privés de la classe externe, mais je suppose qu'il y a un héritage implicite entre les deux classes?

34voto

Jon Skeet Points 692016

Il n'y a pas implicite de l'héritage impliqués aussi loin que je peux dire. Je me serais attendu à ce bien - bien que j'imagine quelque chose d'étrange si A et B sont des termes génériques.

Il est spécifié dans la section 10.1.4 de la spécification:

Si une classe B dérive de la classe, c'est une erreur de compilation pour Un de dépendent B. Une classe dépend directement sur sa classe de base directe (le cas échéant) et dépend directement de la classe au sein d' qui il est immédiatement imbriquée(si tout). Compte tenu de cette définition, l' ensemble complet de classes sur lesquelles un classe dépend de la transitif fermeture de la dépend directement de la relation.

J'ai mis en évidence la section correspondante.

Ce qui explique pourquoi le compilateur est le rejet, mais pas pourquoi la langue de l'interdit. Je me demande si il y a un CLI restriction...

EDIT: Bon, j'ai eu une réponse de Eric Lippert. Fondamentalement, il serait techniquement possible (il n'y a rien dans la CLI pour l'interdire), mais:

  • Permettant il serait difficile, dans le compilateur, d'invalider les différentes hypothèses actuelles autour de la commande et des cycles
  • C'est assez étrange décision de conception, ce qui est plus facile d'interdire que de soutenir

Il a également été noté dans l'email de fil qu'il ferait ce genre de chose valide:

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

... mais ce serait déjà (comme indiqué par Tinister) sera valide que si B dérivée de A.

L'imbrication + héritage = étrangeté...

13voto

Whaledawg Points 2018

Ce n'est pas une chose C # autant que c'est une chose de compilateur. L'un des travaux d'un compilateur consiste à disposer une classe en mémoire, c'est-à-dire un ensemble de types de données de base, de pointeurs, de pointeurs de fonction et d'autres classes.

Il ne peut pas construire la disposition de la classe A jusqu'à ce qu'il sache quelle est la disposition de la classe B. Il ne peut pas connaître la disposition de la classe B avant d'avoir terminé avec la disposition de la classe A. Dépendance circulaire.

0voto

Jeff Kotula Points 1737

Je pense que l'imbrication est censée représenter que le type imbriqué fait partie de la définition du type d'imbrication. Avec cette interprétation, la limitation a un sens car au moment où le compilateur atteint la définition de A, AB n'est pas encore défini, et même à la fin de A, il est déjà défini en termes de AB

0voto

Tinister Points 3649

Concernant les questions sur ce que je tente de faire:

En gros, j'ai voulu créer une classe qui a une composition relation avec lui-même, mais je ne voulais pas que le contenu de l'objet de contenir d'autres objets et, par conséquent, créer une chaîne avec de nombreux "a a-a a a-a a a-a a a-a..." les relations. Donc, ma pensée à l'époque était de faire quelque chose comme ceci:

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

    private AA _containedObject;
}

Ce qui à l'époque semblait assez lisse mais avec le recul je ne suis pas si sûr...

J'avais fouillé dans Google et n'ai pas trouvé de discussion sur elle de sorte que je pensais que je poste ici.

Cependant, dans les commentaires d'un post à Eric Lippert Blog , il donne des exemples d'une classe de mise en œuvre d'un ensemble d'interface ainsi que d'une classe implémentant une interface générique, avec une classe imbriquée comme le type de l'argument (qui ne se compile pas et qu'il appelle un "bug" dans le compilateur actuel). Ces deux exemples concernent les interfaces, donc je me demandais si il y avait quelques règles spéciales avec des classes imbriquées. Et il semble qu'il en existe.

-2voto

bruno conde Points 28120

Cela n'a aucun sens pour moi ... Vous essayez d'étendre quelque chose qui n'existe pas !!! La classe B n'existe que dans le cadre de la classe A et à cause de cela, je pense qu'il y a une sorte d'héritage.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X