Access outer class members from a nested class

M

Matthew Ireland

I would like to access the members of an outer class from methods in an
inner class. I know the following works, but I was hoping for something a
little more elegant. For example, the JAVA syntax of
Outer.this.m_OuterValue does not exist apparently.

class Outer
{
private int m_OuterValue;
class Inner
{
Outer m_pOuter;
public Inner(Outer pOuter)
{
m_pOuter = pOuter;
}
public void InnerMethod()
{
Console.WriteLine("Outer value is: " + m_pOuter.m_OuterValue);
}
}

static void Main(string[] args)
{
Outer pOuter = new Outer();
pOuter.m_OuterValue = 1;
Inner pInner = new Inner(pOuter);
pInner.InnerMethod();
pOuter.m_OuterValue = 2;
pInner.InnerMethod();
Console.WriteLine("Press any key...");
Console.ReadKey();
}
}
 
P

Peter Duniho

Matthew said:
I would like to access the members of an outer class from methods in an
inner class. I know the following works, but I was hoping for something a
little more elegant. For example, the JAVA syntax of
Outer.this.m_OuterValue does not exist apparently.

Java has two different kinds of nested classes. It's important to
understand Java, before one makes the attempt to apply Java concepts to C#.

The type of nested class you appear to be thinking of is an "inner
class". An inner class has an implicit reference to an instance of the
outer class, determined at the time of instantiation, based on the
instance of the outer class that created the inner class.

Obviously, this means that when creating an inner class in Java, you
must always do it via an instance of the outer class. It also then
provides the implicit ability to always access members of the outer
class, but specifically in the instance of the outer class that created
the inner class.

The other kind of nested class in Java is the "static nested class".
This type of nested class must be declared with the keyword "static",
which in that context has a completely different meaning from the use of
the word "static" elsewhere. That is, the class itself can still be
instantiable; it just means that it has no implicit reference to an
instance of the outer class.

Now, what does this all mean for C#? Well, C# doesn't have the concept
of an "inner class". All nested classes are like Java's "static nested
class". This has a couple of consequences: 1) you can have nested
classes that are actually "static" in the same sense of "static" for
top-level classes -- that is, they contain only static members, and 2)
while the nested class has the same accessibility to members of the
containing class that applies in Java, you must always provide an
explicit reference to an instance of that containing class in order to
access instance members of the containing class.

So, the code example you showed is the only approach in C# you can use.

By the way, please note that "elegant" is in the eye of the beholder.
The Java approach adds an unnecessary complexity and inefficiency to the
language, by overloading the "static" keyword, and by making the default
for nested classes carry around a reference to the containing class, as
well as obfuscating the relationship between the code that is written
and what effect it has (because outer class members can be accessed
implicitly).

Pete
 
M

Matthew Ireland

Many thanks for the explanation. That makes sense...

Though I think the paradigm for "static nested class" is the same as a
static method or variable, i.e."you don't need an instance to access it".
So in that light "static" is not really overloaded. The oddity is when you
think of "static" as meaning "there is only one instance shared by all class
instances". So "static" itself is a little bi-polar to begin with.

But then the error you get from the C# compiler when you try to access the
outer class says you can't access non-static members. So the C# syntax has
an implicit "static" attached to the behavior of nested classes, which is
less explicit than the Java approach. This is definately a simplifying
assumption (and we all know about assumptions). I guess I was thinking that
passing a reference to the parent object was a bit brute force. But in the
light of the nested class behaving as a static member, it is the only way.

The problem with either approach is the violation of the second definition
of "static". As a class you want to be able to make independent instances
of the class, but as a "static" member you only want one instance to be
shared.

Oh well...

All development is a compromise.

Thanks again.
 
P

Peter Duniho

Matthew said:
Many thanks for the explanation. That makes sense...

Though I think the paradigm for "static nested class" is the same as a
static method or variable, i.e."you don't need an instance to access it".
So in that light "static" is not really overloaded. The oddity is when you
think of "static" as meaning "there is only one instance shared by all class
instances". So "static" itself is a little bi-polar to begin with.

True. My point is that in C#, the keyword only has one meaning when
applied to classes. It's not overloaded in that context.
But then the error you get from the C# compiler when you try to access the
outer class says you can't access non-static members.

Look at the error carefully. It's simply the same error you get any
time you try to access instance members without an instance. The fact
that the code trying to do the accessing is in a nested class turns out
not to be pertinent to the error.
So the C# syntax has
an implicit "static" attached to the behavior of nested classes, which is
less explicit than the Java approach.

Yes and no. In C#, there's no such thing as an "inner class" as Java
understands it. There's no "implicit 'static'", because an explicit
"static" means something completely different (and uniformly so in any
context).
This is definately a simplifying
assumption (and we all know about assumptions). I guess I was thinking that
passing a reference to the parent object was a bit brute force. But in the
light of the nested class behaving as a static member, it is the only way.

Implicitness carries an appearance of elegance, but appearances can be
deceiving sometimes. :) The thing is, in C# there's never even an idea
of "the parent object" as far as the class declaration hierarchy goes.
On the other hand, you can always design your objects so that they have
parents, but that's always a data structure design aspect, never a class
declaration design aspect.

So, sure...you always have to be explicit about referencing a parent
object in C#. But to the extent that that's because C# doesn't conflate
class declaration structure with the actual data structure, I find a
certain elegance there. And IMHO it's only "brute force" in the sense
that any time you have to actually write code instead of having the
compiler read your mind is "brute force". So at the very least, it's no
worse "brute force" than most of the rest of the code you have to write. :)

Pete
 
J

J.B. Moreno

Matthew Ireland said:
Many thanks for the explanation. That makes sense...

Though I think the paradigm for "static nested class" is the same as a
static method or variable, i.e."you don't need an instance to access it".
So in that light "static" is not really overloaded. The oddity is when you
think of "static" as meaning "there is only one instance shared by all class
instances". So "static" itself is a little bi-polar to begin with.

As Peter explained, only in Java. In C#, static only has the single
meaning.

This makes C# more consistent, less complex AND gives it more options.

Because in Java all inner class methods have implicit access to the
instance of the enclosing class, a inner class can't have static
members or properties.

In C# an inner class is simply another class, declaring it as an inner
class only determines access and visibility, not function.

I don't see why you'd want to have Java inner classes, I see no benefit
in the implicit access as opposed to the explicit access. At best it
saves a bit of typing, but not a whole lot, and it does so at the
expense of clarity (i.e. you have to be familiar with the class in
order to know whether a property or method belongs to the parent or the
inner class, adding a property or method with the same name invisibly
overrides the parent with the same name).

I don't mind syntactic sugar but it should be explicit and precise.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top