Welcome to MSDN Blogs Sign in | Join | Help

C# nested classes are like C++ nested classes, not Java inner classes

When you declare a class inside another class, the inner class still acts like a regular class. The nesting controls access and visibility, but not behavior. In other words, all the rules you learned about regular classes also apply to nested classes.

The this keyword in an instance methods of a class (nested or not) can be used to access members of that class and only those members. It cannot be used to access members of other classes, at least not directly. (And the this can be omitted when it would not result in ambiguity.) You create an instance of a class (nested or not) by saying new ClassName(...) where ... are the parameters to an applicable class constructor.

Java nested classes behave the same way, but Java also has the concept of inner classes. To construct an instance of an inner class in Java, you write new o.InnerClass(...) where ... as before are the parameters to an applicable class constructor. The o in front is an expression that evaluates to an object whose type is that of the outer class. The inner class can then use the this keyword to access its own members as well as those of the instance of the outer class to which it was bound.

In C++ and C#, you will have to implement this effect manually. It's not hard, though:

// Java
class OuterClass {
 string s;
 // ...
 class InnerClass {

  public InnerClass() { }
  public string GetOuterString() { return s; }
 }
 void SomeFunction() {
  InnerClass i = new this.InnerClass();
  i.GetOuterString();
 }
}
// 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();
 }
}

In Java, the inner class has a secret this$0 member which remembers the instance of the outer class to which it was bound. Creating an instance of an inner class via the new o.InnerClass(...) notation is treated as if you had written new InnerClass(o, ...), where o is automatically assigned to the secret this$0 member, and attempts to access members of the outer class are automatically treated as if they were written this$0.outermember. (This description of how inner classes are implemented is not just conceptual. It is spelled out in the language specification.)

The C# equivalent to this code merely makes explicit the transformation that in Java was implicit. We give the inner class a reference to the outer class (here, we called it o_) and pass it as an explicit parameter to the inner class's constructor. And when we want to access a member of that outer class, we use o_ to do it.

In other words, Java inner classes are syntactic sugar that is not available to C#. In C#, you have to do it manually.

If you want, you can create your own sugar:

class OuterClass {
 ...
 InnerClass NewInnerClass() {
  return new InnerClass(this);
 }
 void SomeFunction() {
  InnerClass i = this.NewInnerClass();
  i.GetOuterString();
 }
}

Where you would want to write in Java new o.InnerClass(...) you can write in C# either o.NewInnerClass(...) or new InnerClass(o, ...). Yes, it's just a bunch of moving the word new around. Like I said, it's just sugar.

Now, I'm not saying that the Java way of representing inner classes isn't useful. It's a very nice piece of sugar if you access the outer class's members frequently from the inner class. However, it's not the type of transformation that makes you say, "Well, if a language doesn't support this, it's too hard for me to implement it manually, so I'll just give up." The conversion is not that complicated and consists entirely of local changes that can be performed without requiring a lot of thought.

As a postscript, my colleague Eric Lippert points out that JScript.NET does have instance-bound inner classes.

class Outer {
 var s;
 class Inner {
  function GetOuterString() {
   return s;
  }
 }
}

var o = new Outer();
o.s = "hi";
var i = new o.Inner();
i.GetOuterString();
Published Tuesday, August 01, 2006 7:00 AM by oldnewthing
Filed under:

Comments

# re: C# nested classes are like C++ nested classes, not Java inner classes

Tuesday, August 01, 2006 10:19 AM by Anonymous coward
This is cruel.
Most java evangelists tell to their believers that C# has too much syntactic sugar. :D.

# re: C# nested classes are like C++ nested classes, not Java inner classes

Tuesday, August 01, 2006 10:26 AM by Tom
I'm glad to see that the inner C# class has access to the outer class's private members.  The current C++ standard does not allow that type of access without a friend declaration.  If memory serves, Pete Becker in a recent issue of Dr. Dobb's Journal (I miss you CUJ! *sniff* ) made mention that the latest C++ draft standard will allow for C#-like access semantics.  [Note: After searching hard for verification on the C++ Committe Website, I have been unable to corroborate my own statement; it may, in fact, be totally wrong!]

# re: C# nested classes are like C++ nested classes, not Java inner classes

Tuesday, August 01, 2006 10:46 AM by Phill
IIRC Java actually supports both types. If you declare your inner class with the static keyword then it will not have any access to the outer class. This saves the implicit reference being added by the compiler.
Inner classes were a necessity in Java due to the event model, your inner class could implement IFocusListener (or whatever) and access the private members of the outer class to perform some action on the event.

# re: C# nested classes are like C++ nested classes, not Java inner classes

Tuesday, August 01, 2006 10:55 AM by Michiel Salters
Tom's technically right. Inner classes were accidentily left out of the list of members that could access the (outer) classes private parts.
I'm not sure any compiler actually enforced that rule, and e.g. VC2005 certainly doesn't. So in practice this restriction doesn't matter.

# re: C# nested classes are like C++ nested classes, not Java inner classes

Tuesday, August 01, 2006 11:13 AM by KJK::Hyperion
"In C++, your friends can see your privates"

# re: C# nested classes are like C++ nested classes, not Java inner classes

Tuesday, August 01, 2006 12:02 PM by Jeroen Frijters
The (bizarre) Java syntax for instantiating an inner class is actually:

this.new InnerClass();

# re: C# nested classes are like C++ nested classes, not Java inner classes

Tuesday, August 01, 2006 12:02 PM by lf
The Java syntax is sligthly off, it's "object.new InnerClass()".

In 98% of cases the object is 'this', and you can just use "new InnerClass()".

# re: C# nested classes are like C++ nested classes, not Java inner classes

Tuesday, August 01, 2006 12:18 PM by JavaSharp
I suspect the reason this is in Java and not in C# is because C# has delegates, whereas Java must rely on inner classes (specifially, "anonymous inner classes").

# Explicit This in Inner Classes

Tuesday, August 01, 2006 12:48 PM by Brian Vargas
I agree with JavaSharp's statement.  The primary reason that inner classes are useful in Java is the lack of delegates.

Also, it's interesting to note the awful syntax when you want to do an explicit reference from an inner class method to a containing class member:

Outerclass.this.s = "foo";

Ugh.

However, it can be necessary when the inner class has a member with the same name as the outer class, and one needs to access the outer class method from the inner class.

# re: C# nested classes are like C++ nested classes, not Java inner classes

Tuesday, August 01, 2006 1:16 PM by Anonymous coward
But are not delegates just syntactic sugar?

http://java.sun.com/docs/white/delegates.html

"We believe bound method references are unnecessary because another design alternative, inner classes, provides equal or superior functionality..."
"We believe bound method references are harmful because they detract from the simplicity of the Java programming language...."

[In a sense, everything beyond "if" and "goto" is syntactic sugar. If you prefer your code unsweetened, nobody's forcing you to add sugar. -Raymond]

# re: C# nested classes are like C++ nested classes, not Java inner classes

Tuesday, August 01, 2006 1:24 PM by Smartass
AC: Yes, but it's not the type of transformation that makes you say, "Well, if a language doesn't support this, it's too hard for me to implement it manually, so I'll just give up."

:-)

# re: C# nested classes are like C++ nested classes, not Java inner classes

Tuesday, August 01, 2006 5:32 PM by Luke Hutteman
"Java inner classes are syntactic sugar"

True: in the exact same way that non-virtual instance methods are syntactic sugar over static methods ;-)

# re: C# nested classes are like C++ nested classes, not Java inner classes

Tuesday, August 01, 2006 6:58 PM by NoDotNet
"Not actually a .Net blog"

# protected virtual void jaysonBlog { : Working On Some CSModules

# re: C# nested classes are like C++ nested classes, not Java inner classes

Tuesday, August 01, 2006 8:18 PM by Dean Harding
> But are not delegates just syntactic sugar?
>
> http://java.sun.com/docs/white/delegates.html

They just don't like delegates because they're not "object-oriented" enough for Java. They seem to think this idea of "everything is an object" adds to the "simplicity" of Java. I love this essay:

http://steve-yegge.blogspot.com/2006/03/execution-in-kingdom-of-nouns.html

# re: C# nested classes are like C++ nested classes, not Java inner classes

Tuesday, August 01, 2006 9:16 PM by silkio
lack of delegates aren't the reason for inner classes in java.

inner classes are useful for hashmap nodes, enumerators, and any other object who's existence is based in the life of the parent object.

# re: C# nested classes are like C++ nested classes, not Java inner classes

Tuesday, August 01, 2006 10:05 PM by steven
any particular reason you chose to refer to third party spec instead of official Sun's spec?

[That was the first spec I found. -Raymond]

# re: C# nested classes are like C++ nested classes, not Java inner classes

Wednesday, August 02, 2006 9:36 AM by andy
You've got a bad google-fu (http://ask.metafilter.com/mefi/21557), Raymond :P

First hit for this search: http://www.google.no/search?q=java+language+specification
.. is http://java.sun.com/docs/books/jls/ :)

Similar with MSN Search, btw.

[Well, yeah, but I wasn't searching for the java language specification. I was looking for pages that talked about java inner classes. -Raymond]

# re: C# nested classes are like C++ nested classes, not Java inner classes

Wednesday, August 02, 2006 9:58 AM by Darren Winsper
Is there a reason the Java-like behaviour wasn't adopted?  After all, Java does support both methods, it wouldn't have been hard for C# to do the same thing.

[Minus 100 points. -Raymond]

# re: C# nested classes are like C++ nested classes, not Java inner classes

Wednesday, August 02, 2006 9:08 PM by Norman Diamond
> [Minus 100 points. -Raymond]

Perhaps Mr. Winsper will be reassured to know that Mr. Chen wasn't rating Mr. Winsper's posting ^_^  The link points to the minus 100 points posting that really explains the answer.

(The linked posting doesn't entirely explain if the answer is good or not, which of course is the subject of enough debates itself.  It does explain what this answer is.)

# re: C# nested classes are like C++ nested classes, not Java inner classes

Friday, August 04, 2006 4:36 AM by Neil
Why not get rid of the syntactic sugar that allows you to write i.GetOuterString() and write Outer_Inner_GetOuterString(i) instead ;-)

# Would you like to have function pointer as syntactic sugar?

Friday, August 04, 2006 5:13 AM by Steven Yong's Weblog
There's been a lot of debates out there recently about how useful is the method reference (or function pointer) in programming or scripting languages such as JavaScript, C# and J++. It looks like Java turns out to be the loser in this debate because it

# Implicit Evaluation with PHP » Blog Archive » History of the World, Part XII: Wherein Java covers its eyes and proclaims “You Can’t See Me!”

# .Net Learning Curve » Blog Archive » C# nested classes (vs Java)

New Comments to this post are disabled
 
Page view tracker