{"id":2574,"date":"2017-02-18T11:37:34","date_gmt":"2017-02-17T23:37:34","guid":{"rendered":"https:\/\/www.deltics.co.nz\/blog\/?p=2574"},"modified":"2017-02-18T11:37:34","modified_gmt":"2017-02-17T23:37:34","slug":"anonymous-classes-identity-exposed","status":"publish","type":"post","link":"https:\/\/www.deltics.co.nz\/blog\/posts\/2574\/","title":{"rendered":"Anonymous Classes: Identity Exposed!"},"content":{"rendered":"<span class=\"span-reading-time rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\">[Estimated Reading Time: <\/span> <span class=\"rt-time\"> 2<\/span> <span class=\"rt-label rt-postfix\">minutes]<\/span><\/span><p>In <a href=\"https:\/\/www.deltics.co.nz\/blog\/posts\/2523?preview_id=2523\">my previous post on Anonymous Classes<\/a> I erroneously referred to them as &#8220;dynamic objects&#8221; (thanks to commentors for pulling me up on that).<\/p>\n<p>Dynamic objects are something else entirely (although what <em>precisely<\/em> they might mean can vary on different platforms and in different languages).  I have now corrected that post on this point, and also on <a href=\"https:\/\/twitter.com\/dwarfland\/status\/831463486010056705?cn=cmVwbHk%3D\">another point that Marc Hoffman called me out on<\/a> (again, thanks for that).<\/p>\n<p>And so the time has now come to expose the <strong>true<\/strong> identity of these so called &#8220;Anonymous Classes&#8221;.<\/p>\n<p><!--more--><\/p>\n<p>This won&#8217;t be a very long post since the identity of an anonymous class is not especially well hidden.  It&#8217;s just that knowing that identity is not very useful (to us as application developers &#8211; it is of course crucial to the compiler).<\/p>\n<p>So all that is required is a very simple example:<\/p>\n<pre class=\"brush: oxygene; title: ; notranslate\" title=\"\">\r\nnamespace anonClassName;\r\n\r\n  type\r\n    Program = class\r\n    public\r\n      class method Main(args: array of String): Int32;\r\n      begin\r\n        var anon := new class( foo := 'The question ?', bar := 42);\r\n        var obj  := new Object;\r\n\r\n        writeLn(typeOf(anon));\r\n        writeLn(typeOf(obj));\r\n\r\n        readLn;\r\n      end;\r\n    end;\r\n\r\nend.\r\n<\/pre>\n<p>Using the (optional) <a href=\"https:\/\/www.deltics.co.nz\/blog\/posts\/2470\">inline implementation syntax now supported in Oxygene<\/a>, this implements a simple console application which instantiate an anonymous class with 2 (two) members, good ol&#8217; <strong>foo<\/strong> and <strong>bar<\/strong>.  For comparison, a simple <strong>object<\/strong> is also instantiated for comparison.<\/p>\n<p>I then use the <strong>typeOf()<\/strong> Oxygene intrinsic to report the name of the type (i.e. class) of each of these objects.<\/p>\n<p>The output is equally simple:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n&lt;&gt;f__AnonymousType0`2&#x5B;System.String,System.Int32]\r\nSystem.Object\r\n<\/pre>\n<p>And as we can see, the &#8220;so called&#8221; anonymous class isn&#8217;t actually anonymous at all.  With a slightly extended example we gain a little more insight:<\/p>\n<pre class=\"brush: oxygene; title: ; notranslate\" title=\"\">\r\n        var anonA := new class( foo := 'The question ?', bar := 42);\r\n        var anonB := new class( foo := 'Another question ?', bar := 147);\r\n        var anonC := new class( foo := 10, bar := 2 );\r\n\r\n        writeLn(typeOf(anonA));\r\n        writeLn(typeOf(anonB));\r\n        writeLn(typeOf(anonC));\r\n<\/pre>\n<p>Running this yields:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n&lt;&gt;f__AnonymousType0`2&#x5B;System.String,System.Int32]\r\n&lt;&gt;f__AnonymousType0`2&#x5B;System.String,System.Int32]\r\n&lt;&gt;f__AnonymousType1`2&#x5B;System.Int32,System.Int32]\r\n<\/pre>\n<p>Here we can see that <strong>anonA<\/strong> and <strong>anonB<\/strong> are actually of the same type.  I don&#8217;t know precisely how the compiler works and whether context is a component in the algorithm for deriving a class name, but at the very least we can see that in this case the fact that the two classes have the same members mean that even though both are instantiated anonymously and separately, they are of the same type.<\/p>\n<p>This (in part) is what presumably enables the use of strongly typed collections of even anonymous class instances in LINQ, for example.<\/p>\n<p>Equally we can see that even though <strong>anonC<\/strong> has the same member names as <strong>anonA<\/strong> and <strong>anonB<\/strong>, it is a distinct type, courtesy of the <em>types<\/em> of those members.<\/p>\n<p>As noted, those type names are not very friendly, would not even be legal (or certainly not straightforward) to use in any code and in theory I think could change from one build to the next.<\/p>\n<p>But now the secret of anonymous classes is revealed.  They aren&#8217;t anonymous so much as just very discreet <em>and<\/em> discrete.  \ud83d\ude42<\/p>\n","protected":false},"excerpt":{"rendered":"<p><span class=\"span-reading-time rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\">[Estimated Reading Time: <\/span> <span class=\"rt-time\"> 2<\/span> <span class=\"rt-label rt-postfix\">minutes]<\/span><\/span>In my previous post on Anonymous Classes I erroneously referred to them as &#8220;dynamic objects&#8221; (thanks to commentors for pulling me up on that). Dynamic objects are something else entirely (although what precisely they might mean can vary on different platforms and in different languages). I have now corrected that post on this point, and [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"jetpack_post_was_ever_published":false},"categories":[4,180],"tags":[311,13,181],"class_list":["post-2574","post","type-post","status-publish","format-standard","hentry","category-delphi","category-oxygene","tag-anonymous-classes","tag-language","tag-oxygene-2"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p1TKYv-Fw","jetpack_sharing_enabled":true,"jetpack-related-posts":[],"_links":{"self":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts\/2574","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/comments?post=2574"}],"version-history":[{"count":3,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts\/2574\/revisions"}],"predecessor-version":[{"id":2577,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts\/2574\/revisions\/2577"}],"wp:attachment":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/media?parent=2574"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/categories?post=2574"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/tags?post=2574"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}