Internals of Anonymous Types





5.00/5 (2 votes)
Internals of Anonymous Types
.NET comes with lots of new features as it introduces new features. Many of them are quite useful while others might be very specific to an issue. One of the features that came up recently with the introduction of .NET 3.5 in C# is anonymous method. Anonymous means an object with no name. Before .NET 3.5, we had concept of anonymous delegates in C#. If you read about internals of delegate, you must already know how anonymous delegates are declared to CLR. In fact, there is no concept of anonymous in MSIL. Hence everything that you see as anonymous is actually a level of abstraction to us, and lets us to avoid the complexity to maintain unnecessary types to our program. In this post, I will discuss about anonymous type in terms of MSIL.
The Basics
Anonymous types are those types which are not declared before they are used. Say while you are doing your program, you want a temporary storage of your data, what you need to do, you need either declare a concrete class for the storage of the same, or you can use any collection like ArrayList
, HashTable
, etc. to store the key value collection. C# 3.5 and onwards allows you to dynamically create a type and use it directly in your program. You can use ‘var
’ or implicit type declaration to ensure you could use the properties just like normal types.
var myruntimeObject = new { FirstProperty = 10, SecondProperty = new DateTime(),
ThirdProperty = "string type" };
Console.WriteLine("Type of myruntimeObject is {0}", myruntimeObject.GetType().Name);
Console.WriteLine("Type of FirstProperty is {0}",
myruntimeObject.FirstProperty.GetType().Name);
Console.WriteLine("Type of SecondProperty is {0}",
myruntimeObject.SecondProperty.GetType().Name);
Console.WriteLine("Type of ThirdProperty is {0}",
myruntimeObject.ThirdProperty.GetType().Name);
Console.Read();
In the above example, I have created one anonymous type using var
. The var
will give you a chance to get intellesense in your code. You can see the variable holds an object of an anonymous type generated runtime. The power of var
in code can also be tested. Just hover over the var
keyword and you will see that the type is defined as anonymous.
In the previous code after the declaration of anonymous object, I have tried to see what exactly the type of the object and the members look like that I have declared. Let's see the output below:
So the actual type created by CLR at runtime looks like <>f_AnnonymousType0`3
. We will discuss about it later in this post, but the thing that you might wonder, is the compiler is smart enough to declare the type of the members exactly. The FirstProperty
is declared as Int32
, second as DateTime
and third as String
. The type is self evaluated in the code and declared accordingly.
Now if I change the value just a bit like:
var myruntimeObject = new
{
FirstProperty = 10d,
SecondProperty = new DateTime(),
ThirdProperty = "string type"
};
The code says the FirstProperty
is double
. The 10d
is evaluated as double
value.
You are also free to declare anonymous type for its members.
var myruntimeObject = new { FirstProperty = 10,
SecondProperty = new DateTime(), ThirdProperty = "string type",
MoreProperty = new { N1 = "" } };
Here the MoreProperty
declares another anonymous type implicitly. But there is restriction in the usage of anonymous types. You cannot declare a method inside any object declaration, even there is no way to give accessibility specifier to its members. All the members inside an anonymous type are readonly properties, hence if you try to do:
myruntimeObject.FirstProperty = 20;
It will prompt you an error.
Another important thing about anonymous type is that the compiler is smart enough to use anonymous type gracefully. It does not create a new anonymous type if the next instruction exactly tries to create the same class. Hence if you use:
var myruntimeObject = new { FirstProperty = 10, SecondProperty = new DateTime(),
ThirdProperty = "string type", MoreProperty = new { N1 = "" } };
var myruntimeObject2 = new { FirstProperty = 30, SecondProperty = new DateTime(),
ThirdProperty = "string type2", MoreProperty = new { N1 = "blah blah" } };
Both internally represent the same type.
The Internals
Now as you know the basics of anonymous Types, let's look deep into its internal structure. In terms of IL, both var
and anonymous type is nothing. Var
is actually represented as actual type while anonymous type is mapped to an actual type.
The object creation looks similar to:
<>f__AnonymousType0<<N1>j__TPar> moreproperty = new <>f__AnonymousType0<<N1>j__TPar>("");
<>f__AnonymousType1<<FirstProperty>j__TPar,
<SecondProperty>j__TPar, <ThirdProperty>j__TPar, <MoreProperty>j__TPar>
myruntimeObject = new
<>f__AnonymousType1<<FirstProperty>j__TPar,
<SecondProperty>j__TPar, <ThirdProperty>j__TPar,
<MoreProperty>j__TPar>(10, new DateTime(), "string type", moreproperty);
Hence, it seems to be quite a big name for the type and also includes a generic argument named <N1>j__TPar
. This lets the object to refer to the same type when argument differs. As Reflection API is not good enough to show the actual generic types, it shows a numeric representation for the same.
Now as you can see, the Compiler generated type for MoreProperty
looks like the one above. The first thing that you should notice is the DebuggerDisplayAttribute
just above class. With this attribute, Visual Studio debugger shows only <anonymous type> rather than the whole type name.
The Type
takes a Generic type argument <N1>j__TPar
in its constructor and builds the class. You should notice the parameter is marked as Readonly
, so it is not writable. Also the type overrides ToString
, GetHashCode
and Equals
by using the generic EqualityComparer
. This looks like a nice implementation.
Conclusion
Finally, to conclude, I must say anonymous types is an interesting feature which is widely used and eventually changed the way of coding. It is very much useful while working with LINQ. We will discuss internals of LINQ in a later part of the series. But there should be a provision to define methods inside an anonymous type, which I think will be added sooner than later.
I hope you like my post. Give your feedback.
Happy coding.