Каков наилучший способ доступа к полю во вложенном классе из вложенного класса? - PullRequest
55 голосов
/ 09 октября 2008

Скажите, если у меня есть выпадающий список в форме, и у меня есть другой вложенный класс внутри этого класса. Теперь, как лучше всего получить доступ к этому выпадающему списку из вложенного класса?

Ответы [ 8 ]

71 голосов
/ 09 октября 2008

В отличие от Java, вложенный класс не является специальным «внутренним классом», поэтому вам нужно будет передать ссылку. У Раймонда Чена есть пример, описывающий различия здесь: Вложенные классы C # похожи на вложенные классы C ++, а не внутренние классы Java .

Вот пример, в котором конструктору вложенного класса передается экземпляр внешнего класса для дальнейшего использования.

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

}

Обратите внимание, что InnerClass может получить доступ к "s" OuterClass, я не изменял код Рэймонда (как я упоминал выше), поэтому помните, что "string s;" это private, потому что нет других разрешение доступа было указано.

30 голосов
/ 09 октября 2008

Вложенные типы не похожи на внутренние классы в Java - нет встроенного экземпляра содержащего типа. (Они больше похожи на статические вложенные классы в Java.) Это фактически отдельные классы с двумя отличиями:

  • Если содержащий тип является универсальным, вложенный тип эффективно параметризуется с помощью содержащего типа, например, Outer<int>.Nested отличается от Outer<string>.Nested.
  • Вложенные типы имеют доступ к закрытым членам в содержащем типе.
12 голосов
/ 09 октября 2008

В отличие от Java, в C # нет неявной ссылки на экземпляр включающего класса.

Вам нужно передать такую ​​ссылку на вложенный класс. Типичный способ сделать это - через конструктор вложенного класса.

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";
        }
    }
}
8 голосов
/ 16 апреля 2015

Статические члены

Поскольку никто до сих пор не упомянул об этом: В зависимости от вашей ситуации , если переменная-член также может быть статической , вы можете просто получить к ней доступ следующим образом.

class OuterClass
{
    private static int memberVar;

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

Sidenote: Я целенаправленно (и избыточно) пометил memberVar как private, чтобы проиллюстрировать данную способность вложенного класса получать доступ к закрытым членам своего внешнего класса.

Внимание / Пожалуйста, примите во внимание

В некоторых ситуациях это может быть самый простой способ / обходной путь для получения доступа, но ...

  • Static также означает, что переменная будет общей для всех объектов экземпляра, со всеми имеющимися недостатками / последствиями (потокобезопасность и т. Д.)

  • Static также означает, что это, очевидно, не будет работать, если у вас более одного экземпляра класса родителя, и переменная должна содержать индивидуальное значение для каждого экземпляра

Так что в большинстве случаев вы можете пойти другим путем ...

Передача ссылки

Как и предлагало большинство людей (и потому что это также самый правильный ответ), вот пример передачи ссылки на экземпляр внешнего класса.

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; }
    }
}
4 голосов
/ 28 июля 2014

Еще один метод, который полезен при определенных обстоятельствах, заключается в извлечении вложенного класса из внешнего класса. Вот так:

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

Я использовал эту технику, особенно в контексте Структурированных юнит-тестов . (Это может не относиться к конкретному вопросу OP, но может быть полезно для вложенных классов в целом, как в случае этого «дублирующего» вопроса: « Могу ли я получить доступ к объектам внешнего класса во внутреннем классе » )

1 голос
/ 09 октября 2008

Поправьте меня, если я ошибаюсь, вы пытаетесь обработать внешний контроль со стороны внутреннего класса, следовательно, вы столкнулись с этим. Лучшим способом сделать это было бы управление делами в зависимости от событий. Используйте шаблон Observer, зарегистрируйте слушателя на внешнем элементе управления (ваш вложенный / внутренний класс будет слушателем). Делает жизнь проще. Боюсь, что это не тот ответ, которого вы ожидали!

0 голосов
/ 22 сентября 2016

отправка мастер-класса в качестве параметра конструктора для вложенного (внутреннего) класса.

0 голосов
/ 09 октября 2008

Вы можете передать включающий класс как параметр в конструктор вложенного класса, например:

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

Вложенные классы, как правило, не рекомендуются и должны быть закрытыми и / или внутренними. Хотя, на мой взгляд, иногда они полезны.

...