Rick Strahl's Weblog  

Wind, waves, code and everything in between...
.NET • C# • Markdown • WPF • All Things Web
Contact   •   Articles   •   Products   •   Support   •   Advertise
Sponsored by:
West Wind WebSurge - Rest Client and Http Load Testing for Windows

Anonymous Types in C# 3.0


:P
On this page:

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.:

AnonymousTypeIntellisense

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:

AnonymousTypeAssembly2

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.  

Posted in CSharp  LINQ  

The Voices of Reason


 

yaip
November 15, 2007

# re: Anonymous Types in C# 3.0

This is not related to this post. But it would be great if you can (if you have no already) post about using dates. What to store in DB if the date is blank, how to find out and what to display if date is not entered, while creating a row - what to pass, etc. Basically your thoughts and techniques you would use.

Steve from Pleasant Hill
November 15, 2007

# re: Anonymous Types in C# 3.0

Kind of reminds me of Pascal Record data types.

Daniel Moth
November 16, 2007

# re: Anonymous Types in C# 3.0

Nice write up. I think it would be useful if we all started referring to these things as C# 3.0/VB9 features instead of .NET 3.x given that we can use them in .NET 2.0 projects as well.

yaip
November 16, 2007

# re: Anonymous Types in C# 3.0

Some of the features (like this one) is available both in VB.NET as well as C#. Where as some of the features like Automatic Properties only is available in C#.

It would be nice to have a table that would show new features and the language it is available in. Something like:

Feature C# VB.NET
-------------------------------------------------------------
Anonymous
Types Y Y

Automatic
Properties Y N

Bryan Watts
November 16, 2007

# re: Anonymous Types in C# 3.0

Hi Rick! Excellent post.

Sorry to post off-topic, but: what syntax highlighter do you use? I haven't found a solution that meets my blog's needs and your code samples always look great.

Rick Strahl
November 16, 2007

# re: Anonymous Types in C# 3.0

@Daniel - isn't that what I did here? <g> Well, we have Microsoft to thank for the runtime confusion that surrounds the new features versions. I sure wish a more sane convention would have been used. Certainly .NET 3.x should have not been a 3.x but 2.5 or something to that effect... too late. Hopefully uptake and installations of 3.5 will happen quickly so in the future we can forget about this versioning madness. Maybe 4.0 will consolidate everything - yeah right.

@Bryan - I use Live Writer for my posts with the CopySourceAsHtml add-in in Visual Studio. I then use paste as Html in Live Writer. There are also a couple of Paste from Visual Studio plugins for live writer but I actually find the combination of the above the best solution because the VS add-in is highly configurable about how text gets pasted. I've been meaning to take that add-in code (it comes with source) and create another LiveWrite plug in that does all of that in one pass, but I haven't had time...

Daniel Moth
November 27, 2007

# re: Anonymous Types in C# 3.0

@Rick - LOL.. yeah that's what you did until the last sentence (last word even?) of the post that spoiles it <g>.

@yaip - Not a table, but a graphic/slide showing the overlap of each language feature cross C# and VB is on my blog.

Thiarley Fontenele
April 22, 2008

# re: Anonymous Types in C# 3.0

Hi, can I serialize anonymous Types?

Paul
September 17, 2008

# re: Anonymous Types in C# 3.0

Great article,

Is there a way, like in javascript, to create an object from a JSON or XML string using Anonymous types?

That would be pretty neat!

Rick Strahl
September 12, 2009

# re: Anonymous Types in C# 3.0

@Paul - unfortunately not. All the built in serialization relies on preexisting types to deserialize JSON.

Otherwise you'd have to build an object structure on the fly. It might be possible to do something like this in C# 4.0 dynamic types to trap method not found errors and route to a property bag of some sort.

Still not an easy proposition - parsing JSON without a type template is much more complex than when you know

BlueRaja
March 30, 2010

# re: Anonymous Types in C# 3.0

"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."
I've opened a feature request about this on Microsoft Connect - give your support if you feel it would be useful.

https://connect.microsoft.com/VisualStudio/feedback/details/542278/ability-to-return-strongly-typed-anonymous-classes#

Priya
May 16, 2011

# re: Anonymous Types in C# 3.0

Very much helpful for the beginners like me. Thanks a lot :)

West Wind  © Rick Strahl, West Wind Technologies, 2005 - 2024