Каков наилучший способ доступа к полю в охватывающем классе из вложенного класса?

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

Ответ 1

В отличие от Java, вложенный класс не является специальным "внутренним классом", поэтому вам нужно будет передать ссылку. У Раймонда Чена есть пример, описывающий различия: вложенные классы С# похожи на вложенные классы 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 потому что никакие другие права доступа не были указаны.

Ответ 2

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

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

Ответ 3

В отличие от Java, в С# нет неявной ссылки на экземпляр класса-оболочки.

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

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

Ответ 4

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

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

class OuterClass
{
    private static int memberVar;

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

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

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

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

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

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

Ответ 5

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

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, но это может быть полезно для вложенных классов в целом, как в случае с этим "повторяющимся" вопросом: "Могу ли я получить доступ к объектам внешнего класса во внутреннем классе" )

Ответ 6

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

Ответ 7

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

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

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

Ответ 8

отправить мастер-класс в качестве параметра конструктора во вложенный (внутренний) класс.