In my previous post on Anonymous Classes I erroneously referred to them as “dynamic objects” (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 also on another point that Marc Hoffman called me out on (again, thanks for that).
And so the time has now come to expose the true identity of these so called “Anonymous Classes”.
This won’t be a very long post since the identity of an anonymous class is not especially well hidden. It’s just that knowing that identity is not very useful (to us as application developers – it is of course crucial to the compiler).
So all that is required is a very simple example:
namespace anonClassName; type Program = class public class method Main(args: array of String): Int32; begin var anon := new class( foo := 'The question ?', bar := 42); var obj := new Object; writeLn(typeOf(anon)); writeLn(typeOf(obj)); readLn; end; end; end.
Using the (optional) inline implementation syntax now supported in Oxygene, this implements a simple console application which instantiate an anonymous class with 2 (two) members, good ol’ foo and bar. For comparison, a simple object is also instantiated for comparison.
I then use the typeOf() Oxygene intrinsic to report the name of the type (i.e. class) of each of these objects.
The output is equally simple:
And as we can see, the “so called” anonymous class isn’t actually anonymous at all. With a slightly extended example we gain a little more insight:
var anonA := new class( foo := 'The question ?', bar := 42); var anonB := new class( foo := 'Another question ?', bar := 147); var anonC := new class( foo := 10, bar := 2 ); writeLn(typeOf(anonA)); writeLn(typeOf(anonB)); writeLn(typeOf(anonC));
Running this yields:
<>f__AnonymousType0`2[System.String,System.Int32] <>f__AnonymousType0`2[System.String,System.Int32] <>f__AnonymousType1`2[System.Int32,System.Int32]
Here we can see that anonA and anonB are actually of the same type. I don’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.
This (in part) is what presumably enables the use of strongly typed collections of even anonymous class instances in LINQ, for example.
Equally we can see that even though anonC has the same member names as anonA and anonB, it is a distinct type, courtesy of the types of those members.
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.
But now the secret of anonymous classes is revealed. They aren’t anonymous so much as just very discreet and discrete. 🙂