¿Cuál es la mejor forma de acceder al campo en la clase adjunta de la clase anidada?

Di si tengo un menú desplegable en un formulario y tengo otra clase anidada dentro de esta clase. Ahora, ¿cuál es la mejor manera de acceder a este menú desplegable de la clase anidada?

A diferencia de Java, una clase anidada no es una “clase interna” especial, por lo que necesitaría pasar una referencia. Raymond Chen tiene un ejemplo que describe las diferencias aquí: las clases anidadas de C # son como las clases anidadas de C ++, no las clases internas de Java .

Aquí hay un ejemplo donde el constructor de la clase anidada pasa la instancia de la clase externa para referencia posterior.

// 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(); } } 

Tenga en cuenta que InnerClass puede acceder a la ” s ” de la OuterClass, no modifiqué el código de Raymond (como he vinculado anteriormente), así que recuerde que la ” string s; ” es private porque no se especificó ningún otro permiso de acceso.

Los tipos nesteds no son como las clases internas en Java; no hay una instancia inherente del tipo contenedor. (Son más como clases anidadas estáticas en Java). Son clases efectivamente separadas, con dos distinciones:

  • Si el tipo contenedor es genérico, el tipo nested se parametriza de manera efectiva por el tipo que lo contiene, por ejemplo, Outer.Nested no es lo mismo que Outer.Nested .
  • Los tipos nesteds tienen acceso a miembros privados en el tipo contenedor.

A diferencia de Java, en C # no hay referencia implícita a una instancia de la clase adjunta.

Debe pasar tal referencia a la clase anidada. Una forma típica de hacerlo es a través del constructor de la clase anidada.

 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"; } } } 

Miembros estáticos

Dado que nadie lo ha mencionado hasta ahora: Dependiendo de su situación , si la variable miembro también puede ser estática , puede acceder a ella de la siguiente manera.

 class OuterClass { private static int memberVar; class NestedClass { void SomeFunction() { OuterClass.memberVar = 42; } } } 

Nota: memberVar propósito (y redundantemente) como private para ilustrar la capacidad dada de la clase anidada para acceder a los miembros privados de su clase externa.

Precaución / Por favor considere

En algunas situaciones, esta podría ser la forma más fácil / alternativa de obtener acceso, pero …

  • Estático también significa que la variable se compartirá en todos los objetos de instancia, con todas las desventajas / consecuencias que existen (seguridad de subprocesos, etc.)

  • Estático también significa que, obviamente, esto no funcionará si tiene más de una instancia de la clase principal y la variable debe contener un valor individual para cada instancia

Entonces, en la mayoría de los casos, quizás quieras ir con un enfoque diferente …

Pasando una referencia

Como la mayoría de la gente ha sugerido (y porque también es la respuesta más correcta), aquí un ejemplo de pasar una referencia a la instancia de la clase externa.

 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; } } } 

Otro método, que es útil bajo ciertas circunstancias, es derivar la clase anidada de la clase externa. Al igual que:

 class Outer() { protected int outerVar; class Nested() : Outer { //can access outerVar here, without the need for a // reference variable (or the associated dot notation). } } 

He usado esta técnica especialmente en el contexto de las Pruebas de unidades estructuradas . (Esto puede no aplicarse a la pregunta particular del OP, pero puede ser útil con clases anidadas en general, como en el caso de esta pregunta “duplicada”: ” ¿Puedo acceder a los objetos de la clase externa en la clase interna? “)

Corrígeme si estoy equivocado, estás tratando de procesar el control externo de la clase interna, por lo tanto, te topaste con esto. Una mejor forma de hacerlo sería manejar los asuntos de una manera impulsada por eventos. Use un patrón Observer, registre un oyente en el control externo (su clase anidada / interna será el oyente). Simplifica la vida ¡Temo que esta no sea la respuesta que esperabas!

Puede pasar la clase adjunta como un parámetro al constructor de clase nested, como este:

 private NestedClass _nestedClass; public ParentClass() { _nestedClass = new NestedClass(this); } 

Las clases anidadas generalmente no son recomendables y deben ser privadas o internas. Sin embargo, en mi opinión, son útiles a veces.

envíe la clase maestra como un parámetro constructor a la clase anidada (interna).