Learner
Learner

Reputation:

What's the best way of accessing field in the enclosing class from the nested class?

Say if I have a dropdown in a form and I have another nested class inside of this class . Now what's the best way to access this dropdown from the nested class?

Upvotes: 74

Views: 52378

Answers (9)

afshar003
afshar003

Reputation: 839

there is a good answer above but I like to write sth.

c# nested class is by default private

private to containing class if your want to use it must be public

Upvotes: -1

Ray Hayes
Ray Hayes

Reputation: 15015

Unlike Java, a nested class isn't a special "inner class" so you'd need to pass a reference. Raymond Chen has an example describing the differences here : C# nested classes are like C++ nested classes, not Java inner classes.

Here is an example where the constructor of the nested class is passed the instance of the outer class for later reference.

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

}

Note that the InnerClass can access the "s" of the OuterClass, I didn't modify Raymond's code (as I linked to above), so remember that the "string s;" is private because no other access permission was specified.

Upvotes: 95

Jon Skeet
Jon Skeet

Reputation: 1503260

Nested types aren't like inner classes in Java - there's no inherent instance of the containing type. (They're more like static nested classes in Java.) They're effectively separate classes, with two distinctions:

  • If the containing type is generic, the nested type is effectively parameterised by the containing type, e.g. Outer<int>.Nested isn't the same as Outer<string>.Nested.
  • Nested types have access to private members in the containing type.

Upvotes: 35

Hamid Jolany
Hamid Jolany

Reputation: 880

send the master class as an constructor parameter to the nested (inner) class.

Upvotes: 0

kmote
kmote

Reputation: 16765

One other method, which is useful under certain circumstances, is to derive the nested class off of the outer class. Like so:

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

I have used this technique especially in the context of Structured Unit Tests. (This may not apply to the OP's particular question, but it can be helpful with nested classes in general, as in the case of this "duplicate" question: " Can i access outer class objects in inner class ")

Upvotes: 4

Levite
Levite

Reputation: 17637

Static Members

Since no one has mentioned it so far: Depending on your situation, if the member variable can also be static, you could simply access it in following way.

class OuterClass
{
    private static int memberVar;

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

Sidenote: I marked memberVar purposefully (and redundantly) as private to illustrate the given ability of the nested class to access private members of it's outer class.

Caution / Please consider

In some situations this might be the easiest way/workaround to get access, but ...

  • Static also means, that the variable will be shared across all instance objects, with all the downsides/consequences there are (thread-safety, etc.)

  • Static also means, that this will obviously not work if you have more than one instance of the parent's class and the variable should hold an individual value for each instance

So in most cases you might wanna go with a different approach ...

Passing a Reference

As most people have suggested (and because it is also the most correct answer), here an example of passing a reference to the outer class' instance.

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

Upvotes: 11

questzen
questzen

Reputation: 3297

Correct me if I am wrong, you are trying to process the outer control from inner class hence you ran into this. A better way of doing this would be to handle affairs in a event driven fashion. Use an Observer pattern, Register a listener on the outer control (your nested/inner class will be the listener). Makes life simpler. I am afraid that this is not the answer you were expecting!

Upvotes: 1

mannu
mannu

Reputation: 793

You could pass the enclosing class as a parameter to the nested class constructor, like this:

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

Nested classes are generally not recommended and should be private and/or internal. They are, in my opinion, useful sometimes though.

Upvotes: 1

Jason Kresowaty
Jason Kresowaty

Reputation: 16530

Unlike Java, in C# there is no implicit reference to an instance of the enclosing class.

You need to pass such a reference to the nested class. A typical way to do this is through the nested class's constructor.

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

Upvotes: 13

Related Questions