Скажем, если у меня есть раскрывающийся список в форме, и у меня есть еще один вложенный класс внутри этого класса. Как лучше всего получить доступ к этому раскрывающемуся списку из вложенного класса?
Каков наилучший способ доступа к полю в охватывающем классе из вложенного класса?
Ответы (9)
В отличие от 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
, потому что не было указано другое разрешение на доступ.
Вложенные типы не похожи на внутренние классы в Java — в них нет неотъемлемого экземпляра содержащего типа. (Они больше похожи на статические вложенные классы в Java.) Фактически это отдельные классы с двумя отличиями:
- Если содержащий тип является универсальным, вложенный тип эффективно параметризуется содержащим типом, например.
Outer<int>.Nested
не то же самое, чтоOuter<string>.Nested
. - Вложенные типы имеют доступ к закрытым членам содержащего типа.
В отличие от 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";
}
}
}
Form1 form = new Form1(); new Nested(form);
является допустимым.
- person Stevens Miller; 12.02.2018
Статические члены
Поскольку до сих пор об этом никто не упоминал: В зависимости от вашей ситуации, если переменная-член также может быть статической, вы можете просто получить к ней доступ следующим образом.
class OuterClass
{
private static int memberVar;
class NestedClass
{
void SomeFunction() { OuterClass.memberVar = 42; }
}
}
Примечание: я намеренно (и избыточно) пометил memberVar
как private
, чтобы проиллюстрировать данную возможность вложенного класса для доступа к закрытым членам своего внешнего класса.
Осторожно / Пожалуйста, учтите
В некоторых ситуациях это может быть самым простым способом/обходным решением для получения доступа, но...
Статический также означает, что переменная будет совместно использоваться всеми объектами экземпляра со всеми недостатками/последствиями (потокобезопасность и т. д.).
Статический также означает, что это, очевидно, не будет работать, если у вас есть более одного экземпляра родительского класса, и переменная должна содержать отдельное значение для каждого экземпляра.
Поэтому в большинстве случаев вы можете использовать другой подход...
Передача ссылки
Как предлагали большинство людей (и потому что это также самый правильный ответ), здесь пример передачи ссылки на экземпляр внешнего класса.
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; }
}
}
Еще один метод, полезный при определенных обстоятельствах, заключается в получении вложенного класса от внешнего класса. Вот так:
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, но может быть полезно для вложенных классов в целом, как в случае с этим «дублирующимся» вопросом: « Могу ли я получить доступ к объектам внешнего класса во внутреннем классе ")
Outer
и вам нужен экземпляр Nested
, соответствующий вашему существующему экземпляру Outer
, я не могу Не думаю, что это работает.
- person Sam; 27.03.2015
Поправьте меня, если я ошибаюсь, вы пытаетесь обработать внешний элемент управления из внутреннего класса, поэтому вы столкнулись с этим. Лучшим способом сделать это было бы вести дела в событийно-ориентированной манере. Используйте шаблон Observer, зарегистрируйте слушателя на внешнем элементе управления (ваш вложенный/внутренний класс будет слушателем). Делает жизнь проще. Боюсь, это не тот ответ, которого вы ожидали!
Вы можете передать окружающий класс в качестве параметра конструктору вложенного класса, например:
private NestedClass _nestedClass;
public ParentClass()
{
_nestedClass = new NestedClass(this);
}
Вложенные классы обычно не рекомендуются и должны быть закрытыми и/или внутренними. Хотя, на мой взгляд, они иногда полезны.
отправить мастер-класс в качестве параметра конструктора во вложенный (внутренний) класс.
выше есть хороший ответ, но мне нравится писать что-то.
вложенный класс С# по умолчанию является закрытым
private для содержащего класса если вы хотите использовать его, он должен быть общедоступным