Qual é a melhor maneira de acessar o campo na class de inclusão da class aninhada?

Digamos que eu tenha uma lista suspensa em um formulário e tenha outra class aninhada dentro dessa class. Agora, qual é a melhor maneira de acessar essa lista suspensa da class aninhada?

Ao contrário de Java, uma class aninhada não é uma “class interna” especial, portanto, é necessário passar uma referência. Raymond Chen tem um exemplo descrevendo as diferenças aqui: As classs aninhadas em C # são como classs aninhadas em C ++, não classs internas em Java .

Aqui está um exemplo onde o construtor da class aninhada é passado a instância da class externa para referência 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(); } } 

Note que o InnerClass pode acessar o ” s ” do OuterClass, eu não modifiquei o código do Raymond (como eu fiz o link acima), então lembre-se que a ” string s; ” é private porque nenhuma outra permissão de access foi especificada.

Tipos nesteds não são como classs internas em Java – não há nenhuma instância inerente do tipo de contenção. (Eles são mais como classs aninhadas estáticas em Java.) Eles são efetivamente classs separadas, com duas distinções:

  • Se o tipo de contenção é genérico, o tipo nested é efetivamente parametrizado pelo tipo de contenção, por exemplo, Outer.Nested não é o mesmo que Outer.Nested .
  • Tipos nesteds têm access a membros privados no tipo de contêiner.

Ao contrário do Java, em C # não há referência implícita a uma instância da class envolvente.

Você precisa passar essa referência para a class aninhada. Uma maneira típica de fazer isso é através do construtor da class aninhada.

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

Membros estáticos

Já que ninguém mencionou isso até agora: Dependendo da sua situação , se a variável de membro também puder ser estática , você poderá simplesmente acessá-la da seguinte maneira.

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

Sidenote: Eu marquei o memberVar propositalmente (e redundantemente) como private para ilustrar a habilidade dada da class aninhada para acessar membros privados de sua class externa.

Cuidado / Por favor, considere

Em algumas situações, essa pode ser a maneira mais fácil de contornar o access, mas …

  • Estático também significa que a variável será compartilhada em todos os objects de instância, com todas as desvantagens / consequências que existem (segurança de thread, etc.)

  • Estático também significa que obviamente isso não funcionará se você tiver mais de uma instância da class pai e a variável tiver que conter um valor individual para cada instância

Então, na maioria dos casos, você pode querer uma abordagem diferente …

Passando uma Referência

Como a maioria das pessoas sugeriu (e porque também é a resposta mais correta), aqui está um exemplo de passar uma referência à instância da class 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; } } } 

Um outro método, que é útil sob certas circunstâncias, é derivar a class aninhada fora da class externa. Igual a:

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

Eu usei essa técnica especialmente no contexto de testes de unidade estruturada . (Isso pode não se aplicar à pergunta específica do OP, mas pode ser útil com classs aninhadas em geral, como no caso desta pergunta “duplicada”: ” Posso acessar objects de class externa na class interna “)

Corrija-me se eu estiver errado, você está tentando processar o controle externo da class interna, portanto você se deparou com isso. Uma maneira melhor de fazer isso seria lidar com assuntos em uma forma orientada a events. Use um padrão Observer, registre um ouvinte no controle externo (sua class interna / aninhada será o ouvinte). Torna a vida mais simples. Receio que esta não seja a resposta que esperavas!

Você poderia passar a class envolvente como um parâmetro para o construtor da class aninhada, assim:

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

As classs aninhadas geralmente não são recomendadas e devem ser privadas e / ou internas. Eles são, na minha opinião, úteis às vezes.

envie a class master como um parâmetro construtor para a class aninhada (interna).