フォームにドロップダウンがあり、このクラス内に別のネストされたクラスがあるとします。ネストされたクラスからこのドロップダウンにアクセスする最良の方法は何ですか?
9 に答える
Java とは異なり、ネストされたクラスは特別な「内部クラス」ではないため、参照を渡す必要があります。Raymond Chen は、ここで違いを説明する例を持っています。
ネストされたクラスのコンストラクターが、後で参照するために外部クラスのインスタンスに渡される例を次に示します。
// 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 は OuterClass の " " にアクセスできることに注意してください。Raymond のコードは (上でリンクしたように) 変更していないので、" " は他のアクセス許可が指定されていないためs
であることを覚えておいてください。string s;
private
ネストされた型は、Java の内部クラスとは異なります。含まれている型の固有のインスタンスはありません。(これらは、Java の静的なネストされたクラスに似ています。) これらは実質的に個別のクラスであり、次の 2 つの違いがあります。
- 含まれる型がジェネリックである場合、ネストされた型は、含まれる型によって効果的にパラメーター化されます。たとえば、 isn
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";
}
}
}
静的メンバー
これまで誰も言及していないので、状況に応じて、メンバー変数も静的にすることができる場合は、次の方法で簡単にアクセスできます。
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; }
}
}
特定の状況下で役立つもう 1 つの方法は、外側のクラスからネストされたクラスを派生させることです。そのようです:
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の特定の質問には当てはまらないかもしれませんが、この「重複した」質問の場合のように、一般的にネストされたクラスに役立ちます:「内部クラスの外部クラスオブジェクトにアクセスできますか」)
私が間違っている場合は修正してください。内部クラスから外部コントロールを処理しようとしているため、これに遭遇しました。これを行うためのより良い方法は、イベント駆動型の方法で業務を処理することです。オブザーバー パターンを使用し、外側のコントロールにリスナーを登録します (ネストされた/内側のクラスがリスナーになります)。生活をよりシンプルにします。残念ながら、これはあなたが期待していた答えではありません!
次のように、囲んでいるクラスをパラメーターとしてネストされたクラス コンストラクターに渡すことができます。
private NestedClass _nestedClass;
public ParentClass()
{
_nestedClass = new NestedClass(this);
}
入れ子になったクラスは一般に推奨されず、プライベートおよび/または内部にする必要があります。私の意見では、それらは時々役に立ちます。
マスター クラスをコンストラクター パラメーターとしてネストされた (内部) クラスに送信します。