8
votes

2 cles C # contiennent les uns les autres en tant que membre

J'ai deux classes C # a, b.

et le code est quelque chose comme ça xxx

est-ce encore possible? Si c'est ce que signifie cela signifie? A Objet de B qui a un objet d'un .... Cela peut continuer ..


6 commentaires

Fondamentalement classe est un type défini par l'utilisateur. Donc, vous pouvez utiliser comme ça.


Pourquoi pensez-vous que ce serait un problème? Il peut continuer et sur - mais également, objet1 ou objet2 peut être null .


@DANPUZEY Votre commentaire stipule que vous avez oublié C ++ un peu. En C ++, cela nécessite des efforts supplémentaires pour résoudre ce problème. En C #, ce n'est pas étrange de demander si le compilateur peut résoudre celui-ci sans autre déclaration.


@GRv Évitez les dépendances circulaires autant que possible. Essayez-le (avec votre IDE) si une sous-traitance sera atteinte sans autre déclaration C #. (en C ++, cela nécessiterait de nouveaux travaux)


@Mnémonic: Je ne sais pas ce que vous voulez dire; C ++ n'est pas pertinent pour cette question (c'est une question C #) et il n'y a absolument aucun problème avec ce code en C #. Si l'OP disait "Je m'attendrais à ce que cela pose problème, car en C ++, c'est un problème", c'est un contenu différent.


Un cas particulier de votre question est quand a est B, comme classe publique A {public un parent; } . Vous pouvez le trouver par ex. dans la construction singleton.


5 Réponses :


0
votes

Vous aurez une dépendance cyclique / circulaire.


2 commentaires

Pouvez-vous élaborer plus sur cela.


Que veux-tu dire par là? Je ne vois pas comment c'est le cas du tout.



0
votes

Il est possible, mais le mot clé de la définition de classe en c # est class et non classe .


0 commentaires

4
votes

C'est bien possible et dans de nombreux cas souhaitables, dans de telles structures telles que les relations parents / enfants, etc. Vous pouvez même avoir un membre d'une classe qui est de la même classe (comme dans un arbre hiérarchique).

Mais ce que vous ne pouvez pas avoir est: xxx

qui peut être la source de confusion, car le compilateur ne pourra pas dire quelle est la classe de base et laquelle est la dérivé un.


0 commentaires

0
votes

Si les deux classes sont dans des DLL séparées, vous aborderez dans beaucoup de problèmes de référence circulaires de la DLL (évitez).

Vous avez également créé un problème de référence circulaire si vous Serialise ( Référence circulaire lors de l'utilisation de XML Sérialisation? )

sinon c'est une définition valide et utile dans la plupart des cas.


0 commentaires

4
votes

Est-ce que cela est encore possible? p>

Bien sûr, il est possible - vous pouvez le confirmer en compilant. P>

Si c'est ce que signifie cela signifie? A Object de B qui a un objet d'un .... Cela peut continuer .. p> blockQuote> BlockQuote>

Pour comprendre cela, vous devez comprendre la différence entre les types de valeur ( struct code>) et les types de référence ( class code>). p>

Vous pouvez penser à la structure comme une seule pièce de mémoire simple. Tous les champs de structure sont juste placés un par un. Si certains de ces champs sont également des structures, tous les champs de cette structure «enfant» doivent être placés à l'intérieur de cette pièce de mémoire simple de structure «parent», etc. Ainsi, lorsque vous déclarez une variable de type de valeur, vous connaissez bien, exactement, comment chaque domaine de cette structure sera aligné dans une pièce de mémoire. Et avec struct forte> il est pas possible strong> d'avoir des cas comme vous l'avez mentionné, lorsqu'un champ de B qui a un champ d'a etc. P>

types de référence (classes) sont différents types de choses. Lorsque vous utilisez la valeur du type de référence, vous opérez avec réellement référence forte> à une pièce de mémoire. Vous pouvez penser à la référence (alors que ce n'est pas exactement vrai, mais simplifie vraiment les choses) comme un numéro entier. Donc, chaque fois que vous utilisez une variable de type de référence, quel que soit le type, vous pouvez simplement utiliser sa référence, une valeur int. Les membres de la classe elle-même créés en pièces de mémoire séparées. Donc, tout ce que vous avez avec des références dans votre cas - c'est quelque chose comme ceci: p> xxx pré>

ou, quelque chose comme ça p> xxx pré>

Rien de mal avec une telle définition, vous avez deux objets qui se font référence, comme le parent connaissant son enfant, et l'enfant connaissant son parent. P>

Il est possible car la classe A ne devrait pas garder tous les champs de classe B - Ayez juste une référence em> (numéro d'entier) à un autre objet. p>

CLR et Compiler vous aide à identifier les types de ces références, mais essentiellement au cas de classes se référencant d'autres que les classes références à quelques autres classes. P>

Une différence de plus significative entre STRUCTION ET CLASSE - Lorsque vous déclarez une variable de type de valeur, vous êtes la créer em>, réservation de mémoire pour elle etc.; Lorsque vous déclarez une variable de type de référence, vous êtes Création de référence em>, qui sera initialisé en tant que référence null code>, référençant ainsi nulle part. Il est donc facile de créer des instances des champs de classe A et de classe B - Theres, il suffit de référencer nulle part; Mais il est impossible de créer de telles structures A et B, car vous devriez tout créer à la fois, ce qui est impossible avec du temps et de la mémoire limités. P>

et une petite expérience pour le prouver. Considérer deux cas. Tout d'abord comme celui en question: p> xxx pré>

il compile sans problèmes. P>

et seconde similaire à la première, mais avec des structures: p>

    public struct Struct_A { public Struct_B b; }
    public struct Struct_B { public Struct_A a; }


2 commentaires

Que se passerait-il si nous avions des initialistes qui ont instancié une nouvelle instance de chaque membre? Je suppose que cela compilerait bien, mais nous obtiendrions une exception StackoverFlow à l'heure d'exécution, non?


Si vous voulez dire constructeur, alors sûr, c'est une récursive comme A: .ctor () -> B: .ctor () -> A: .ctor -> ... etc., qui est pur. Comme toute récursion, il sera compilé, car il s'agit du développeur de l'arrêter au besoin. Fondamentalement, c'est ce que j'essaie de décrire - lorsque vous avez besoin d'une chaîne entière entière à la fois, elle n'est pas possible. Si vous pouvez créer d'abord des objets, puis créer des relations pour eux (comme pour le graphique avec des cycles, créez d'abord des sommets de graphique, puis attribuez des relations de bord entre eux) - alors il est absolument «légal» et possible.