{"id":30273,"date":"2006-08-01T10:00:19","date_gmt":"2006-08-01T10:00:19","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2006\/08\/01\/c-nested-classes-are-like-c-nested-classes-not-java-inner-classes\/"},"modified":"2006-08-01T10:00:19","modified_gmt":"2006-08-01T10:00:19","slug":"c-nested-classes-are-like-c-nested-classes-not-java-inner-classes","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20060801-19\/?p=30273","title":{"rendered":"C# nested classes are like C++ nested classes, not Java inner classes"},"content":{"rendered":"<p>\nWhen you declare a class inside another class,\nthe inner class still acts like a regular class.\nThe nesting controls access and visibility, but not behavior.\nIn other words, all the rules you learned about regular classes\nalso apply to nested classes.\n<\/p>\n<p>\nThe <code>this<\/code> keyword in an instance methods\nof a class (nested or not)\ncan be used to access members of that class and only those members.\nIt cannot be used to access members\nof other classes, at least not directly.\n(And the <code>this<\/code> can be omitted when it would not result in\nambiguity.)\nYou create an instance of a class (nested or not) by saying\n<code>new ClassName(...)<\/code> where <code>...<\/code> are the\nparameters to an applicable class constructor.\n<\/p>\n<p>\nJava nested classes behave the same way, but Java also has\nthe concept of inner classes.\nTo construct an instance of an inner class in Java, you write\n<code>new o.InnerClass(...)<\/code> where <code>...<\/code> as before\nare the parameters to an applicable class constructor.\nThe <code>o<\/code> in front is an expression that evaluates to\nan object whose type is that of the outer class.\nThe inner class can then use the <code>this<\/code> keyword to\naccess its own members as well as those of the instance of the\nouter class to which it was bound.\n<\/p>\n<p>\nIn C++ and C#, you will have to implement this effect manually.\nIt&#8217;s not hard, though:\n<\/p>\n<table>\n<tr>\n<td>\n<pre>\n\/\/ Java\nclass OuterClass {\n string s;\n \/\/ ...\n class InnerClass {\n  public InnerClass() { }\n  public string GetOuterString() { return s; }\n }\n void SomeFunction() {\n  InnerClass i = new this.InnerClass();\n  i.GetOuterString();\n }\n}\n<\/pre>\n<\/td>\n<td>\n<pre>\n\/\/ C#\nclass OuterClass {\n string s;\n \/\/ ...\n class InnerClass {\n  OuterClass o_;\n  public InnerClass(OuterClass o) { o_ = o; }\n  public string GetOuterString() { return o_.s; }\n }\n void SomeFunction() {\n  InnerClass i = new InnerClass(this);\n  i.GetOuterString();\n }\n}\n<\/pre>\n<\/td>\n<\/tr>\n<\/table>\n<p>\nIn Java,\nthe inner class has a secret <code>this$0<\/code> member\nwhich remembers the instance of the outer class to which it\nwas bound.\nCreating an instance of an inner class via the\n<code>new o.InnerClass(...)<\/code>\nnotation is treated as if you had written\n<code>new InnerClass(o, ...)<\/code>,\nwhere <code>o<\/code> is automatically assigned to the\nsecret <code>this$0<\/code> member,\nand attempts to access members of the outer class\nare automatically treated as if they were written\n<code>this$0.outermember<\/code>.\n(This description of how inner classes are implemented\nis not just conceptual.\n<a HREF=\"http:\/\/www.flex-compiler.csail.mit.edu\/jdk\/guide\/innerclasses\/spec\/innerclasses.doc2.html\">\nIt is spelled out in the language specification<\/a>.)\n<\/p>\n<p>\nThe C# equivalent to this code merely makes explicit\nthe transformation that in Java was implicit.\nWe give the inner class a reference to the outer class\n(here, we called it <code>o_<\/code>) and pass it as\nan explicit parameter to the inner class&#8217;s constructor.\nAnd when we want to access a member of that outer class,\nwe use <code>o_<\/code> to do it.\n<\/p>\n<p>\nIn other words, Java inner classes are syntactic sugar\nthat is not available to C#.\nIn C#, you have to do it manually.\n<\/p>\n<p>\nIf you want, you can create your own sugar:\n<\/p>\n<pre>\nclass OuterClass {\n ...\n InnerClass NewInnerClass() {\n  return new InnerClass(this);\n }\n void SomeFunction() {\n  InnerClass i = this.NewInnerClass();\n  i.GetOuterString();\n }\n}\n<\/pre>\n<p>\nWhere you would want to write in Java\n<code>new o.InnerClass(...)<\/code>\nyou can write in C# either\n<code>o.NewInnerClass(...)<\/code>\nor\n<code>new InnerClass(o, ...)<\/code>.\nYes, it&#8217;s just a bunch of moving the word <code>new<\/code> around.\nLike I said, it&#8217;s just sugar.\n<\/p>\n<p>\nNow, I&#8217;m not saying that the Java way of representing inner classes\nisn&#8217;t useful.\nIt&#8217;s a very nice piece of sugar if you access the outer class&#8217;s\nmembers frequently from the inner class.\nHowever, it&#8217;s not the type of transformation that makes you say,\n&#8220;Well, if a language doesn&#8217;t support this, it&#8217;s too hard for me\nto implement it manually, so I&#8217;ll just give up.&#8221;\nThe conversion is not that complicated and consists\nentirely of local changes that can be performed without requiring\na lot of thought.\n<\/p>\n<p>\nAs a postscript,\nmy colleague\n<a HREF=\"http:\/\/blogs.msdn.com\/ericlippert\/\">\nEric Lippert<\/a>\npoints out that\nJScript.NET does have instance-bound inner classes.\n<\/p>\n<pre>\nclass Outer {\n var s;\n class Inner {\n  function GetOuterString() {\n   return s;\n  }\n }\n}\nvar o = new Outer();\no.s = \"hi\";\nvar i = new o.Inner();\ni.GetOuterString();\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>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) [&hellip;]<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-30273","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>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) [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/30273","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=30273"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/30273\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=30273"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=30273"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=30273"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}