Dites si j'ai une liste déroulante dans un formulaire et que j'ai une autre classe imbriquée à l'intérieur de cette classe . Maintenant, quel est le meilleur moyen d'accéder à cette liste déroulante depuis la classe imbriquée?
Contrairement à Java, une classe imbriquée n'est pas une "classe interne" spéciale, vous devez donc passer une référence. Raymond Chen propose ici un exemple décrivant les différences: Les classes imbriquées C # ressemblent aux classes imbriquées C++, et non aux classes internes Java .
Voici un exemple où le constructeur de la classe imbriquée se voit transmettre l'instance de la classe externe pour une référence ultérieure.
// C#
class OuterClass
{
string s;
// ...
class InnerClass
{
OuterClass o_;
public InnerClass(OuterClass o) { o_ = o; }
public string GetOuterString() { return o_.s; }
}
void SomeFunction() {
InnerClass i = new InnerClass(this);
i.GetOuterString();
}
}
Notez que l'InnerClass peut accéder à la "s
" de l'OuterClass, je n'ai pas modifié le code de Raymond (comme je l'ai lié ci-dessus), donc rappelez-vous que "string s;
" est private
car aucune autre autorisation d'accès n'a été spécifiée.
Les types imbriqués ne ressemblent pas aux classes internes de Java - il n'y a pas d'instance inhérente du type contenant. (Ils ressemblent davantage à des classes imbriquées statiques en Java.) Ce sont en réalité des classes séparées, avec deux distinctions:
Outer<int>.Nested
n'est pas la même chose que Outer<string>.Nested
.Contrairement à Java, en C #, il n’ya pas de référence implicite à une instance de la classe englobante.
Vous devez passer une telle référence à la classe imbriquée. Pour ce faire, utilisez généralement le constructeur de la classe imbriquée.
public partial class Form1 : Form
{
private Nested m_Nested;
public Form1()
{
InitializeComponent();
m_Nested = new Nested(this);
m_Nested.Test();
}
private class Nested
{
private Form1 m_Parent;
protected Form1 Parent
{
get
{
return m_Parent;
}
}
public Nested(Form1 parent)
{
m_Parent = parent;
}
public void Test()
{
this.Parent.textBox1.Text = "Testing access to parent Form's control";
}
}
}
Puisque personne ne l’a mentionné jusqu’à présent: En fonction de votre situation, si la variable membre peut également être static , vous pourrez simplement y accéder de la manière suivante.
class OuterClass
{
private static int memberVar;
class NestedClass
{
void SomeFunction() { OuterClass.memberVar = 42; }
}
}
Sidenote: J'ai marqué memberVar
à dessein (et de manière redondante) avec private
pour illustrer la capacité donnée de la classe imbriquée d'accéder aux membres privés de sa classe externe.
Dans certaines situations, cela pourrait être le moyen le plus simple de contourner le problème, mais ...
Statique signifie également que la variable sera partagée entre tous les objets d'instance, avec tous les inconvénients/conséquences qu'il y a (sécurité des threads, etc.).
Statique signifie également que cela ne fonctionnera évidemment pas si vous avez plus d'une instance de la classe parent et que la variable doit contenir une valeur individuelle pour chaque instance.
Donc, dans la plupart des cas, vous voudrez peut-être adopter une approche différente ...
Comme la plupart des gens l'ont suggéré (et parce que c'est aussi la réponse la plus correcte), voici un exemple de transmission d'une référence à l'instance de la classe externe.
class OuterClass
{
private int memberVar;
private NestedClass n;
OuterClass() { n = new NestedClass(this); }
class NestedClass
{
private OuterClass parent;
NestedClass(OuterClass p) { parent = p; }
SomeFunction() { parent.memberVar = 42; }
}
}
Une autre méthode, utile dans certaines circonstances, consiste à dériver la classe imbriquée de la classe externe. Ainsi:
class Outer()
{
protected int outerVar;
class Nested() : Outer
{
//can access outerVar here, without the need for a
// reference variable (or the associated dot notation).
}
}
J'ai utilisé cette technique notamment dans le cadre de Tests unitaires structurés . (Cela peut ne pas s'appliquer à la question particulière du PO, mais cela peut être utile avec les classes imbriquées en général, comme dans le cas de cette question "en double": " Puis-je accéder aux objets de classe externes dans la classe intérieure ")
Corrigez-moi si je me trompe, vous essayez de traiter le contrôle externe de la classe interne, vous avez donc rencontré ce problème. Une meilleure façon de le faire serait de gérer les affaires de manière événementielle. Utilisez un modèle Observer, enregistrez un écouteur sur le contrôle externe (votre classe imbriquée/interne sera l'écouteur). Rend la vie plus simple. Je crains que ce ne soit pas la réponse à laquelle vous vous attendiez!
Vous pouvez passer la classe englobante en tant que paramètre au constructeur de la classe imbriquée, comme ceci:
private NestedClass _nestedClass;
public ParentClass()
{
_nestedClass = new NestedClass(this);
}
Les classes imbriquées ne sont généralement pas recommandées et doivent être privées et/ou internes. À mon avis, ils sont parfois utiles.
envoie la classe maître en tant que paramètre de constructeur à la classe imbriquée (interne).