Anonymous Types in C#
This is the second in a series of articles about the language and framework features that make Microsoft’s Language Integrated Query (LINQ) possible. The goal of this series is to understand the individual elements of a LINQ statement without the C# syntax sugar hiding the details of how it works.
- Part 1: The C# var type and its usage
An anonymous type is the declaration of a class signature at the same time of its value initialization.
var person = new {FirstName="Bubba", LastName="Jones"};
Console.WriteLine(String.Format("Hello {0} {1}", person.FirstName, person.LastName));
When the compiler processes the first line of this example it creates a new type that has two properties (FirstName and LastName). It gives this type a generated name that the programmer does not know. So how does the programmer reference an instance to a type that she does not know the name of? This is the situation the var keyword was designed for. The compiler knows the type name because it created it. It substitutes the anonymous type it created in for var, just as it would substitute in any built in type like string if the initializing value was a string. As can be seen in the second line of the example the resulting reference is strongly typed. You get an object with two properties whose data types have been inferred to be strings. If you are using Visual Studio you get intellisense for your newly created type as well.
I think a common reaction that developers have when they learn about anonymous types is “I will never have to write another data class again.” Unfortunately this is not the case. It is by design that these type definitions are unnamed, and its the programmer’s inability to explicitly reference these types that makes them almost useless outside of method scope. You can pass an anonymous type into a method as an upcasted System.Object type reference. A good example of this can be seen in the ASP.NET MVC bits where anonymous types are used to initialize Hashtables with a collection of named properties, but because you upcast and lose your strong typing to do this it requires the callee to use reflection to examine what properties exist in the anonymous type. This would not be a good option for passing around the data model of your solution. Anonymous types also do not support method signatures or inheriting from anything other than System.Object.
So if anonymous types are not a practical solution for your data model what can they be used for? It turns out that anonymous types are extremely useful when querying data and producing a result set that is either a combination of different types or a narrowing version of an existing single type. Try to think of it in the context of how you would write a SQL statement to return some records from a table in a database. Does your return always match all of the columns from a single table? Or do you sometimes only return some of the columns from a table, or do you sometimes return a combination of columns from two or more tables after a joining operation. How would you replicate this dynamic result in the strongly typed C#? Without anonymous types you have to create a class definition for every possible result you returned, or create huge classes that accounted for every result possibility. With anonymous types you can have the compiler create these classes for you as you need them, and when the compiler does generate them they only contain the properties you need for the desired result.
Nice post. Well written and easy to understand. Now I will never have to write a data class again! oh wait…
Jason
September 25, 2008 at 10:59 pm