Anonymous types in C# (and .NET 3.5)

So what the heck are anonymous types all about? What’s the difference between a normal type and an anonymous type? First and most important: the anonymous type has no type name. Actually that is not 100% true. The anonymous type has a type name (because all types in .NET need to have one) but it is the compiler who generates the name, not the developer itself and you won’t see it in your code.

Another important difference is that the (C#) compiler generates a type that can only be initialized once and no longer altered afterwards. The type instance is created and some values are assigned to it but later in the code they can’t be changed anymore. The anonymous type is a so called immutable type (= initialize once and never change it again; System.String is another prominent immutable type).

Most often you will find anonymous types as a result of a LINQ query:

class Program
{
        static void Main(string[] args)
        {
                // create a list with dummy users.
                // the user class has a Name and Age property.
                List<User> users = new List<User>();
                users.Add(new User(“Foo”, 12));
                users.Add(new User(“Bar”, 20));
                users.Add(new User(“FooBar”, 15));

                // query the items for user with an age above 14.
                var result = from u in users
                                where u.Age >= 15
                                 // put the result in a anonymous type
                                 select new { u.Name };

                // loop over the result.
                foreach (var item in result)
                {
                        // print out the name of the item.
                        Console.WriteLine(item.Name);
                }
        }
}

This is also why anonymous types have been introduced. They allow us to create a type on the fly and therefore return only certain values of a given named (= non-anonymous) type. This is very handy when only a subset of properties is needed, properties are joined together or even objects are joined together.

But anonymous types can also be used in own code without expressing them in a LINQ expression. For example when variables should be aggregated together for a short period:

// create an anonymous type instance with a name.
var anonymousType = new { Name = name,
        Age = age, Nationality = nationality };

// print the name to the console.
Console.WriteLine(anonymousType.Name);

This might not be found that often in real-life code because anonymous types are limited. They can, for example, not be passed to other methods - well it could be done but that would mean to pass them as System.Object and therefore their properties can only be accessed by using reflection.

// query the items for user with an age above 14.
var result = from u in users
                 join g in calls on u.ID equals g.UserID
                 // put the result in a anonymous type
                 select new { UserName = u.FirstName + ” “ + u.LastName,
                         CallName = g.Name, g.TimeStamp };

This is another example on what we can do with the anonymous types. In this case the LINQ query joins two objects (User and Call) together and as result the user’s name, the call’s name and time stamp are returned. To avoid problems (like the two objects expose the same properties), we can specify the property names of the anonymous type and assign the values to them (this is also done in the example). Even more, in the example, the user name is assigned as a concat of the first and the last name.

Another interesting question is on how the C# compiler exactly translates the code. The following screenshot shows the class that has been generated for the first anonymous type in this post:

The name is completely compiler generated and is also incremented for each new anonymous type in the program. For all the arguments (in our case one) that are passed to the anonymous type an argument in the constructor has been defined. What’s also important to know is that the GetHashCode() and Equals(Object) methods have been overriden. This has been done to allow LINQ to store the anonymous types instances in a dictionary and fetch them later on. This is also why the properties (in this case the Name property) and the internal fields are marked as read-only in the anonymous types. The GetHashCode() method relies on the content of the fields and if they are altered while being in the dictionary the instance can’t be find anymore later on.

Another interesting thing is that the C# compiler recycles anonymous types. This means if we have like two anonymous type’s instances where we specify the exact same properties we will end up with getting the exact same anonymous type:

// query the items for user with an age above 14.
var result = from u in users
                 select new { u.Name };

// create an anonymous type instance with a name.
var anonymousType = new { Name = “Test” };

// prints TRUE to the console.
Console.WriteLine(anonymousType.GetType() == result.First().GetType());

But how to detect anonymous types in an application? Let’s say you have a framework and you want to understand whether a type is an anonymous type. The bad news first: there is no way to be 100% sure that a type is an anonymous type as the name is completely generated by the compiler and there is no flag that says that the given type is an anonymous type. But a heuristic can be implemented to detect at least the anonymous types that are generated by VB.NET and C#:

private static bool CheckIfAnonymousType(Type type)
{
        if (type == null)
                throw new ArgumentNullException(“type”);

        // HACK: The only way to detect anonymous types right now.
        return Attribute.IsDefined(type, typeof(CompilerGeneratedAttribute), false)
                   && type.IsGenericType && type.Name.Contains(“AnonymousType”)
                   && (type.Name.StartsWith(“<>”) || type.Name.StartsWith(“VB$”))
                   && (type.Attributes & TypeAttributes.NotPublic) == TypeAttributes.NotPublic;
}

Attetion: Keep in mind that this is a hack and might not work with future versions of the C# and VB.NET compilers.

Published on Jan 26th, 2008 — Tags: ,
   digg it!    kick it   

2 Comments ( Comments RSS TrackBack )

  1. [...] is not a dynamic language. That’s for sure! Recently, the adding of the var keyword, anonymous types and lambda expressions have added some “dynamic” to the language. But still it’s [...]

    Pingback by Christian Liensberger » Adding some dynamic to C#: interface wrapping — March 21, 2008 @ 4:46 pm

  2. Anonymous Type 1 will be equal to an other only if argument names and numbers and types are same.

    Comment by fgsdf — January 26, 2010 @ 12:34 pm

Leave a comment

You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> [code][/code] [code lang="csharp"][/code].