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

9

74

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?

Jessalin answered 8/10, 2008 at 22:12 Comment(0)
E
93

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.

Etiquette answered 8/10, 2008 at 22:19 Comment(0)
M
34

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.
Museum answered 8/10, 2008 at 22:21 Comment(4)
(about 7 years later...) Do you have any idea why an outer class cannot access private or protected members of the nested class, in the same way a nested class can access outer class members? There were times that this would have come useful and I am wondering if there was a flaw in my design.Connive
@GDS: I don't know why that design decision was taken, but it's usually made sense to me. If you make the nested class private, then it's fine to make the members internal or public, after all.Museum
That's right but can't there be cases where you would want an internal or even public nested class but its private and protected members to be visible by the outer class? Is there an underlying flaw there?Connive
@GDS: All I can say is that I haven't come across those situations myself. I can't speculate as to the precise reasons for the design.Museum
C
13

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";
        }
    }
}
Criticism answered 8/10, 2008 at 22:21 Comment(1)
This would appear also to have the advantage that, unlike Java, an instance of the inner class can access private members of any instance of the outer class, not just the outer-class instance that created the inner-class instance (i.e. Form1 form = new Form1(); new Nested(form); is legal.Nickolenicks
H
11

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; }
    }
}
Hedgehog answered 16/4, 2015 at 11:4 Comment(0)
C
4

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 ")

Care answered 28/7, 2014 at 17:16 Comment(2)
Now that's an interesting idea and a bit different to the other answers. However, I'm pretty sure you can't instantiate a subclass of an existing object instance, so if you already have an Outer instance and want a Nested instance that corresponds to your existing Outer instance, I don't think this works out.Dilatory
The problem here is that creating a new instance of 'Nested will invoke the 'ctor of the outer Class, most likely leading to stack overflow.Arana
M
1

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.

Monarchism answered 8/10, 2008 at 22:23 Comment(0)
G
1

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!

Geek answered 8/10, 2008 at 22:28 Comment(0)
P
0

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

Padding answered 22/9, 2016 at 8:5 Comment(0)
N
-1

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

Nabal answered 31/5, 2021 at 5:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.