One of the most convenient features of C# 3.0 is the ability to create new types 'on the fly' using Anonymous Types. Anonymous Types are essentially compiler generated types that you don't explicitly declare with an official type declaration. Rather you define the type inline as part of the code where you need to use the new type. Furthermore when the type is 'announced' you don't have to explicitly type each of the members that you create on the type due to the new inferred type discovery that's also new in C# 3.0.
The syntax to declare an anonymous type looks something like this:
// *** Create Complex Types 'on the fly'
var Customer = new
{
Company = "West Wind",
Name = "Rick",
Entered = DateTime.Now,
BillRate = 150M
};
This code creates a new instance of an anonymous type - in this case a simple object instance that holds customer data. Once you have declared the type like the above you can then use the type as if there was a full type declaration, so you can access Customer.Company, Customer.BillRate and so forth.
Visual Studio 2008 is also smart enough to figure out the anonymous type for you so when you're in the editor typing away you get Intellisense when you type Customer.:
Notice that the C# compiler fixes up any members that are created and assigns an appropriate type to each. So as you can see in the screenshot BillRate is typed as decimal based on the inferred type which in this case is a literal decimal value. So Company is a string and Entered a DateTime member by the same logic. Type inference is not limited to literal values - so any typed value expression can be used as an input to force the type to be created. As long as the compiler can tell what the base value is the member can be created as a specific type.
You can even take this one step further by nesting anonymous types like this:
// *** Create Complex Types 'on the fly'
var Customer = new
{
Company = "West Wind",
Name = "Rick",
Entered = DateTime.Now,
BillRate = 150M,
Contacts = new
{
Phone = "808 121-1211",
Fax = "808 231-1211",
Email = "rick@west-wind.com"
}
};
Notice the Contacts member which is another anonymous type nested inside the first type.
Anonymous Types are, well, anonymous: Understand the Scoping
One very important aspect to understand about anonymous types is that they are a compiler generated construct. The type is a regular .NET type similar to any other but it has one big limitation: Anonymous types are scoped only to the currently executing method. Because the generated type is anonymous there's no public name for the type that you can access. In other words you can't instantiate the type directly on your own and you can't reference the type outside of the method that created it.
Notice that the type was created using type inference using the var keyword. Within the local method scope the compiler understands all the type semantics of the type so you get strongly typed access to the type including Intellisense.
However, if you plan on creating an anonymous type and then pass it out of the local method scope you end up loosing the type information, because the type is unknown outside of the method that created it. The only way to return an Anonymous type from a method is to return it as type Object, and the only way to access the type members there is through Reflection.
So all you can do to pass out the type is the following:
protected object AnonymousTypes()
{
// *** Create Complex Types 'on the fly'
var Customer = new
{
Company = "West Wind",
Name = "Rick",
Entered = DateTime.Now,
BillRate = 150M,
Contacts = new
{
Phone = "808 121-1211",
Fax = "808 231-1211",
Email = "rick@west-wind.com"
}
};
return Customer;
}
There's no way to return var as a result type, so a generic object is all that you can return. Any calling code can then only access the type using Reflection. Sometimes this might work OK - for example using DataBinding which often uses Reflection anyway on objects - but at other times you have to be careful with these types as they become unwieldy to use externally.
No Type Duplication
Note that if you create two anonymous types that have the exact same type signature in the same assembly, the C# compiler is smart enough to consolidate the anonymous class definition and reuse that type. So if you have code like the following:
protected object AnonymousTypes()
{
// *** Create Complex Types 'on the fly'
var Customer = new
{
Company = "West Wind",
Name = "Rick",
Entered = DateTime.Now,
BillRate = 150M
};
// *** Create Complex Types 'on the fly'
var Customer2 = new
{
Company = "East Wind",
Name = "Richard",
Entered = DateTime.UtcNow,
BillRate = 10M
};
return Customer;
}
only one class is created for the type. The following IL shows the type reference for both local variables to be the same:
.method family hidebysig instance object AnonymousTypes() cil managed
{
.maxstack 5
.locals init (
[0] class <>f__AnonymousType2`4<string, string, valuetype [mscorlib]System.DateTime, valuetype [mscorlib]System.Decimal> Customer,
[1] class <>f__AnonymousType2`4<string, string, valuetype [mscorlib]System.DateTime, valuetype [mscorlib]System.Decimal> Customer2,
[2] object CS$1$0000)
L_0000: nop
L_0001: ldstr "West Wind"
L_0006: ldstr "Rick"
L_000b: call valuetype [mscorlib]System.DateTime [mscorlib]System.DateTime::get_Now()
L_0010: ldc.i4 150
L_0015: newobj instance void [mscorlib]System.Decimal::.ctor(int32)
L_001a: newobj instance void <>f__AnonymousType2`4<string, string, valuetype [mscorlib]System.DateTime, valuetype [mscorlib]System.Decimal>::.ctor(!0, !1, !2, !3)
L_001f: stloc.0
L_0020: ldstr "West Wind"
L_0025: ldstr "Rick"
L_002a: call valuetype [mscorlib]System.DateTime [mscorlib]System.DateTime::get_Now()
L_002f: ldc.i4 150
L_0034: newobj instance void [mscorlib]System.Decimal::.ctor(int32)
L_0039: newobj instance void <>f__AnonymousType2`4<string, string, valuetype [mscorlib]System.DateTime, valuetype [mscorlib]System.Decimal>::.ctor(!0, !1, !2, !3)
L_003e: stloc.1
L_003f: ldloc.0
L_0040: stloc.2
L_0041: br.s L_0043
L_0043: ldloc.2
L_0044: ret
}
Notice that the type is created with a constructor for each of the member fields and each of the values is then assigned as part of the constructor. The actual type for both variables is the same though and it can be found in the - namespace of your compiled assembly:
If you use Reflector to trace back the type reference you can see that indeed only one type was created in the - namespace. The - namespace is the 'generated' namespace that .NET uses internally (another place is for ASP.NET stock project page files which also use this namespacing).
Also notice that the anonymous type is created with READ ONLY Properties. This means that you can create the anonymous type but you can't assign values to it after creation and that any assignment of the type has to always be made as part of the anonymous type declaration. This seems a bit of an odd design choice frankly, but then again if you don't need to create the type and its values on the fly it's probably better to create an explicit type anyway. Personally I think if you can it usually pays to be to explicit with types since you get a type that is reusable and can be passed around more easily. Use of anonymous types usually works best for some sort of final projection or message scenario where the projected type is in effect the final end result that will be iterated over and displayed or passed over the wire with some sort of serialization.
Nested anonymous types are created as separate types that are then referenced in the Getter's code:
.property instance !<Contacts>j__TPar Contacts
{
.get instance !<Contacts>j__TPar <>f__AnonymousType3`5::get_Contacts()
}
Is it really all that useful - DEFINITELY
You may look at the above code and go "yeah so what?" and wonder about some of the limitations of anonymous types. Also, realistically there's nothing happening here that you can't do by hand. If you really look at this from a plain language perspective the anonymous type just creates a type and initializes it for you with the data assigned to the members.
So why is this useful?
First there's use of this functionality as part of LINQ. If you are querying data and you want to filter your result field list by using projection into a custom type, Anonymous Types are used. So if you run a LINQ to SQL query for example:
TimeTrakkerContext context = new TimeTrakkerContext();
var q =
from p in context.ProjectEntities
where p.Customer.CountryId == "US"
select new
{
Project = p.ProjectName,
Company = p.Customer.Company,
Pk = p.Pk
};
You are in fact creating an IQueryable<AnonymousType> which can then be turned into something like a List<AnonymousType>. The fact that an anonymous type can be created on the fly and that it can be done in a single line of code makes it possible for LINQ to utilize this functionality to create custom shaped result types.
There's also convenience - using an anonymous type can be much quicker to code up than creating a separate type and it can also be more descriptive in that that declaration and assignment happen all in the same statement. It has a distinct JavaScript JSON feeling to it and it certainly can be quick and easy in scenarios where it fits.
I've also found Anonymous Types extremely useful for returning result values through serialization and as results for JSON based services. The fact that you can use LINQ to reduce the result data to EXACTLY the set of data that you want to return to a client can be extremely useful especially and HTTP based service scenarios where keeping data on the wire down is useful.
For example here's a method that returns custom time and total recalculation data back to a Web page AJAX client which is called rather frequently.
/// <summary>
/// Ajax Callback method from the page that handles updating
/// the calculation of time totals.
/// </summary>
/// <param name="Pk"></param>
/// <returns></returns>
[CallbackMethod]
public object UpdateTotals(string Pk)
{
int pk = 0;
int.TryParse(Pk, out pk);
// *** Load Entity into Entry.Entity
this.Entry.Load(pk);
// *** Use form controls/formvars to read
// *** this information and update same
// *** as a regular postback page
this.UpdateTotalsOnEntry();
this.Entry.Entity.TimeIn =
TimeUtilities.RoundDateToMinuteInterval(this.Entry.Entity.TimeIn,
App.Configuration.MinimumMinuteInterval,
RoundingDirection.RoundUp);
this.Entry.Entity.TimeOut =
TimeUtilities.RoundDateToMinuteInterval(this.Entry.Entity.TimeOut,
App.Configuration.MinimumMinuteInterval,
RoundingDirection.RoundUp);
this.Entry.CalculateItemTotals();
// *** Return a projected result object
return new { TotalHours = TimeUtilities.FractionalHoursToString( Entry.Entity.TotalHours,"{0}h {1}min"),
ItemTotal = (decimal) Entry.Entity.ItemTotal,
TimeIn = Entry.Entity.TimeIn.ToString("t"),
TimeOut = Entry.Entity.TimeOut.ToString("t") };
}
Rather than passing back a full entity (actually a couple of them) it's much more efficient to shape the result and return exactly the data that the client requires from a callback method via JSON.
I suspect there will be lots of new uses for this feature once we've been using it for a while, but I'm already finding it one of the more powerful new tools in .NET 3.5.
Other Posts you might also like