Pages

Sunday, February 6, 2011

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. Lets 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 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 is 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, lets 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 big name for the type and also includes a generic argument named <N1>j__TPar. This lets the object to refer 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 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 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 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.

4 comments:

  1. Comments mysteriously disappear from this site.

    ReplyDelete
  2. Good One!!
    But you should have also converted the AnonymousType1 using reflection api and shown it to the readers. That would give more clarity as easy to understand for the readers.

    ReplyDelete
  3. Good One!!
    But you should have also converted the AnonymousType1 using reflection api and shown it to the readers. That would give more clarity as easy to understand for the readers.

    ReplyDelete
  4. Hi Abhishek,
    I just wanted to invite you to the indiblogger meet happening in your city after 2 years at
    CII
    DC-36, Sector - 1, Salt Lake City
    Kolkata - 700 064
    Landmark: Behind City Centre.
    Only 200 seats available. Entry is free with loads of fun. Click here to register = http://www.indiblogger.in/bloggermeet.php?id=113 . See you there!

    ReplyDelete

Please make sure that the question you ask is somehow related to the post you choose. Otherwise you post your general question in Forum section.