C# 3.0 for mere mortals, part 3: Anonymous types

In the previous part on C# 3.0 we talked about implicit typing and how you sometimes do not know the exact type that is returned from an expression.

The feature of anonymous types is a powerful addition to the type system of the CLR. It can also be a scary one. No longer will you be able to have control over all types that are available. New ones are added by the compiler for the places where you “implicitly” declare a new type, that does not have a name.

You will create an anonymous type for every situation where you use an expression like:

var anon = new { x, y, someGuid }

It’s not really important to mention what the types of x, y and someGuid are. The mechanism of implicit typing will deduce that. The anon variable if of a new and anonymous type, that is created by the compiler. The compiler will derive the new type from System.Object and give it three properties named x, y and someGuid. Each property will have a corresponding field that is prefixed by an underscore. The expression is actually an instantiation of this anonymous type, and the properties x, y and someGuid are given the values of the variables x, y and someGuid that are used in the new { } call.

You can have some control over the names that are used for the properties. Here’s how:

var q = new { Left = x, Top = y, Key = someGuid };

The type would now have properties Left, Top and Key and the object is instantiated from the values of x, y and someGuid. Literal values are allowed as well:

var q = new { Left = 10, Top = 20, Key = someGuid };

Remember that if you use literals, you must include an identifiable name for the property. This will not compile:

var q = new { 10, “Hello” };

You might wonder what all the fuss is about. “Great, now I have new objects of a type I do not know. Big deal”. And, yes, it is a big deal.

For example, this way you can make smaller versions of existing objects. These are called projections. It is a familiar term in database-land, where a projection is a selection of some of the columns from a table. The same goes here. Also, you can combine some fragments of data into a single object, where you might have had to hold onto several objects to keep around.

Let’s take another look at this. Take the following code fragment:

  staticvoid Main(string
[] args)
    Program theApp = newProgram

  publicvoid AnonymousTypeDemo()
    var q = from p in GetPostings() where p.Blog.Name ==
{ p.PostingID, CommentCount = p.Comments.Count };

    var z = from p in GetPostings() where p.Blog.Name == “athissen”
{ p.UserREF, CommentCount = p.Comments.Count };

In this fragment GetPostings will retrieve a array of Posting objects. Concentrate on the bold parts and ignore the “from”, “where” and “select” keywords (those come from Linq). Here we have two calles to new { }. The two types for q and z hold the same type of information (PostingID and UserREF both are Guids), but two anonymous types will be created anyway, since the property names differ. The names for these are PostingID and UserREF respectively and they are taken from the property names of a Posting object, because we used p.PostingID and p.UserREF.

Were we to change the second line bold’s part to:

 new { PostingID = p.UserREF … },

then the types would be the same. The compiler will only create a single anonymous type and even allow expressions like z = q; One smart compiler I say.

The C# 3.0 specification also states that not only must the types and names of the properties be the same, the order must also be the same: “This definition includes the order of the properties because it is observable and material in certain circumstances, such as reflection“.

The picture to the right is a screenshot from Reflector that shows the anonymous type as <Projection>f__4.

Also note that it would be a compiler error to try the following:

var q = new { Name = “Alex”, Age = 34 };
q = new { Name = “Nicole”, Age = “Unknown” };
q = new { Name = “Nicole”, YearsFromBirth = 28 };

The first line will make the q variable of the anonymous type with a Name and Age property of type string and int. The second line create a type with the same properties , but also of different types. The objects need to be cast explicitly (which cannot be done anyway). The third line has different properties (although of the same types). Again, the compiler cannot cast implictly, nor can you explicitly.

On to the next part.

This entry was posted in Uncategorized. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s