Click here to Skip to main content
15,891,787 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
See more:
Is it possible to access non-static (normal) fields of the outer class from the inner class?. E.g.:

C#
...
public class OuterClass
{
   public int OuterField = 10;
   
   InnerClass InnerObject = new InnerClass();

   public class InnerClass
   {
      public InnerField = 20;
      int AddInnerAndOuter()
      {
         return InnerField + OuterField;
      }
   }
}
...


The compiler error is:
error CS0038: Cannot access a non-static member of outer type 'OuterClass' via nested type 'OuterClass.InnerClass'


Ok. I'm trying to understand the compiler answer. But do I really have to make OuterField static to access it from InnerClass, and thus make whole group of OuterClass instances dependent on the same value of static OuterField? Or do I have to pass OuterField reference to InnerClass to access it? E.g.:

C#
...
public class OuterClass
{
   public int OuterField = 10;

   InnerClass InnerObject = new InnerClass();
   InnerObject.OuterFieldRef = OuterField;

   public class InnerClass
   {
      public OuterFieldRef;
      public InnerField = 20;

      int AddInnerAndOuter()
      {
         return InnerField + OuterFieldRef;
      }
   }
...
}


The question is: Is there a more elegant and simpler way to access non-static outer fields from inner class without make them static and thus having any OuterClass instance unique?
Posted
Updated 7-Sep-11 16:36pm
v5

Oh… First, non-static methods called "instance methods", not "normal". This is the key, by the way. Now, your problem of access has nothing to do with the fact that one class is an inner class of another.

When you say

C#
return InnerField + OuterField;


you really say

C#
return this.InnerField + someInstance.OuterField;


but what is someInstance? There is no such thing. The field OuterField does not exist without some instance.

You see, what are you asking about has nothing to do with "elegance" or "simplicity". This is about understanding what field you want to read, of what object. And why. Your second sample makes no sense at all; you declare names without types; it won't compile.

Now, there is also such aspect as access modifier. The inner class can access the members of the outer, but the outer class can only access internal or public members of the inner. Again, it has nothing to do with static or instance method. These two aspects of access are orthogonal, independent.

—SA
 
Share this answer
 
Comments
Simon Bang Terkildsen 7-Sep-11 23:56pm    
+5
Sergey Alexandrovich Kryukov 8-Sep-11 1:12am    
Thank you, Simon.
--SA
GParkings 8-Sep-11 4:19am    
A believe there is a construct in Java that, superficially, appears to be similar to the .Net nested class construct but is tied to an instance of the outer class rather than the type definition. This can cause some confusion for Java developers that don't fully understand whats going on 'under the hood' trying to apply the same concepts to a .Net language. Not sure if this is the case here but i have heard of it catching people out.
Sergey Alexandrovich Kryukov 8-Sep-11 10:38am    
Thank you for the note. The root cause of such catching is lack of separation of concerns and perhaps bad separations of them in manuals on different languages: mixed up visibility and scope, visibility and access, access and security, etc.
--SA
Wojciech Trybuch 8-Sep-11 16:44pm    
Thank you for all of your very instructive comments after my second post gentlemen. I really appreciate that very... very much. I must have been so... unintelligent not to understand such trivial things! Of course Java! Where is my head !? As far as I'm concerned I had no deal with Java, but...yes, Java is my problem and of course the lack of separation of concerns. That's it! I have to deal with it asap. Now seriously: simply so far I treated outer classes in C# like containers for inner classes rather. But things are not so obvious as they seemed to me. Anyway for me it's a pity there is no possibility to create such a "container" class for other classes in C# so they would share the same "semi-global" variable (or field as you prefer) created in mentioned "container" after instantiate both the inner classes and the "container". Of course such "semi-global" variable couldn't be static in order to allow create totally independent "container" instances. And my apologies for possible inadequate terminology. Regards.
Thanks for the feedback. Ok. I admit I was writting this text in a hurry. Of course my example will not compile. I marked my code snippets with "..." before and after the snippet text. I didn't give the whole example program. But... please don't throw my example with the rubbish completely. I think it deserves a bit of attention. The program below will compile except for the line which is appropriately marked.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace OuterInner
{
    public class OuterClass
    {
        private int OuterField = 10;

        // Below the creation of InnerClass instance is made, so with the  
        // creation of OuterInstance InnerInstance will be created automatically.
        public InnerClass InnerInstance = new InnerClass(); 


        public class InnerClass
        {
            public void PrintOuterField(OuterClass OuterInstance)
            {
                // The line below will not compile. I thought inner instance 
                // of inner class can access directly to fields of instance of
                // outer class provided that inner class are instantiate in
                // the body of outer class. But.. probably it turns out
                // impossible to achieve.
                Console.WriteLine(OuterField); // <- this line will not compile
                
                // On the other hand this line WILL compile despite
                // 'OuterField' is private. This is obvious of course because
                // inner class (as you mentioned) has access to members of the
                // outer class.
                Console.WriteLine(OuterInstance.OuterField);  
            }
        }
        
    }
    
    public class Program
    {
        static void Main(string[] args)
        {
            // The line below creates instance of OuterClass so from that moment
            // OuterInstance (and InnerInstance) exists.
            OuterClass OuterInstance = new OuterClass();  
            OuterInstance.InnerInstance.PrintOuterField(OuterInstance);
            Console.ReadLine();
        }
    }
    
}


As you see I created OuterClass instance in the 'Main' method whereas InnerClass instance was created in the body of the OuterClase and (what is important I think) the InnerClass instance was created automatically in the moment when the OuterClass was instantiating. Therefore briefly speaking after creating instance of OuterClass we have actually both OuterClass and InnerClass instances. Of course I could make the 'OuterField' static. It would be easier to access such field from everywhere (of course provided that it would be public (eventually internal)). But I tried to find a solution to (I repeat this word again) to elegantly get rid of playing with static fields to make every instance of OuterClass completely distinct from its siblings. Actually I have such situation:
collection of collections. Let's name them SuperCollection and SubCollections. First I don't want SuperCollection class to be or to have fields with static apparition (so to speak). SubCollection instances have e.g. one information shared by them all (but again I don't want to store such info in a static field, I think for known reasons). I decided to create a field storing this information in the body of the SuperCollection class in order to every SubCollection instance could make use of it after instantiate SuperCollection without need of storing any reference to SuperCollection instance in every instance of SubCollection. To make completely non-static both SuperCollection and SubCollection classes so far I haven't found any other solution but (as mentioned above) to make another field in every SubCollection containing information about reference to its "container" to get access to mentioned shared SuperCollecttion instance reference-info field. It allows any instance of OuterCollection (and of course InnerCollections) to be unique but such solution is not very convenient (and... elegant) in my opinion on account of additional reference in every SubCollection instance. Maybe I try to ask the question in another way: In outer class is there a way to create some kind of global fields (without using static modifier) for nested classes, so every instance of nested class could use this "global field" transparently after instantiating outer class? If I'm wrong or confuse notions, please enlighten me.
 
Share this answer
 
v3
Why could you not simply pass the outer class pointer as a constructor argument to the inner class? See my slightly modified code sample below. Your sample compiles fine and logic seems fine now.

-Sarah

C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
namespace OuterInner
{
    public class OuterClass
    {
        private int OuterField = 10;
 
        // Below the creation of InnerClass instance is made, so with the  
        // creation of OuterInstance InnerInstance will be created automatically.
        public InnerClass InnerInstance = new InnerClass(); 
 

        public class InnerClass
        {
			OuterClass m_oOuter = null;

			public InnerClass(OuterClass oOuter)
			{
				// Save the outer class pointer for use in a bit.
				this.m_oOuter = oOuter;
			}

            public void PrintOuterField(OuterClass OuterInstance)
            {
                // The line below will not compile. I thought inner instance 
                // of inner class can access directly to fields of instance of
                // outer class provided that inner class are instantiate in
                // the body of outer class. But.. probably it turns out
                // impossible to achieve.
                Console.WriteLine(this.m_oOuter); // <- this line will not compile
                
                // On the other hand this line WILL compile despite
                // 'OuterField' is private. This is obvious of course because
                // inner class (as you mentioned) has access to members of the
                // outer class.
                Console.WriteLine(OuterInstance.OuterField);  
            }
        }
        
    }
    
    public class Program
    {
        static void Main(string[] args)
        {
            // The line below creates instance of OuterClass so from that moment
            // OuterInstance (and InnerInstance) exists.
            OuterClass OuterInstance = new OuterClass();  
            OuterInstance.InnerInstance.PrintOuterField(OuterInstance);
            Console.ReadLine();
        }
    }
}
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900