web-dev-qa-db-ja.com

ネストされたクラスから囲んでいるクラスのフィールドにアクセスする最良の方法は何ですか?

フォームにドロップダウンがあり、このクラス内に別のネストされたクラスがある場合を考えます。ネストされたクラスからこのドロップダウンにアクセスする最良の方法は何ですか?

56
Learner

Javaとは異なり、ネストされたクラスは特別な「内部クラス」ではないため、参照を渡す必要があります。レイモンド・チェンには、ここで違いを説明する例があります: C#のネストされたクラスは、Java内部クラスではなく、C++のネストされたクラスに似ています

ネストされたクラスのコンストラクターが、後で参照するために外部クラスのインスタンスに渡される例を次に示します。

// 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の「s」にアクセスできることに注意してください。レイモンドのコードは変更していません(上記にリンクしました)。したがって、「string s;」はprivate他のアクセス許可が指定されていないため。

73
Ray Hayes

ネストされた型は、Java-含まれる型の固有のインスタンスはありません。内部クラスとは異なります。(Javaの静的なネストされたクラスに似ています。) 2つの区別:

  • 包含型がジェネリックである場合、ネストされた型は、包含型によって効果的にパラメーター化されます。 Outer<int>.NestedOuter<string>.Nestedと同じではありません。
  • ネストされた型は、包含型のプライベートメンバーにアクセスできます。
31
Jon Skeet

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";
        }
    }
}
12
Jason Kresowaty

静的メンバー

これまで誰も言及していないので:状況に応じて、メンバー変数もstaticにできる場合、次の方法でアクセスします。

class OuterClass
{
    private static int memberVar;

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

サイドノート:memberVarprivateとして意図的に(そして冗長に)マークし、ネストされたクラスの特定の機能を説明します。その外部クラスのプライベートメンバーにアクセスします。

注意/検討してください

いくつかの状況では、これがアクセスを取得する最も簡単な方法/回避策かもしれませんが、...

  • また、静的とは、変数がすべてのインスタンスオブジェクト間で共有されることを意味し、すべての欠点/結果があります(スレッドセーフなど)。

  • また、静的は、親のクラスのインスタンスが複数あり、変数が各インスタンスの個別の値を保持する必要がある場合、これは明らかに機能しないことを意味します

だから、ほとんどの場合、あなたは別のアプローチで行きたいかもしれません...

参照を渡す

ほとんどの人が示唆しているように(そしてそれが最も正しい答えでもあるので)、ここでは外部クラスのインスタンスへの参照を渡す例を示します。

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; }
    }
}
9
Levit

特定の状況で役立つもう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).
    }
}

私はこのテクニックを特に Structured Unit Tests のコンテキストで使用しました。 (これはOPの特定の質問には当てはまらないかもしれませんが、この「重複」質問の場合のように、ネストされたクラス一般に役立ちます: " 内部クラスの外部クラスオブジェクトにアクセスできます ")

4
kmote

私が間違っている場合は修正してください、あなたは内部クラスから外部コントロールを処理しようとしているので、これに遭遇しました。これを行うより良い方法は、イベント駆動型の方法で業務を処理することです。オブザーバーパターンを使用し、外部コントロールにリスナーを登録します(ネスト/内部クラスがリスナーになります)。人生をよりシンプルにします。これはあなたが期待していた答えではないのではないかと心配しています。

1
questzen

次のように、ネストしたクラスコンストラクターにパラメーターとして囲みクラスを渡すことができます。

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

ネストされたクラスは通常お勧めできません。プライベートクラスまたは内部クラスにする必要があります。私の意見では、それらは時々有用です。

0
mannu

マスタークラスをコンストラクタパラメーターとしてネストされた(内部)クラスに送信します。

0
Hamid Jolany