C# 3.0 Tutorials: What is Anonymous type?

This is my fourth part of my C# 3.0 tutorials. We have finished learning about automatic properties that introduces new and shorter way of creating the properties, object and collection initializer that gave us the way to initialize the object or collection in shorter and cool way, implicitly typed local variables that can be declared without specifying the type explicitly. I told you that implicitly typed local variables and anonymous type are the best match but I didn’t mention anything about Anonymous type in previous tutorial. Now, it is the time we start discussing about anonymous type which is introduced in C# 3.0.

What’s Anonymous type?

Anonymous type is the type that is created anonymously. Anonymous type is a class that is created automatically by compiler in somewhere you can’t see directly while you are declaring the structure of that class. Confusing? Let me show you one example.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1 {
class Program {
static void Main(string[] args) {
Person _person = new Person { ID = 1, FirstName = "Michael", LastName = "Sync" };
Console.WriteLine("Name: {0} {1}", _person.FirstName, _person.LastName);
Console.ReadLine();
}
}
public class Person {
public int ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
}

Please take a look at the code above. I created a class called Person that has three properties such as ID, FirstName and LastName. In Main() function, I declared a variable and initialized the properties of the instance. Yes. this is just a normal way of creating a class and initializing the instance that we have been doing this for years.

Now, I will change the normal class to anonymous type.
Anonymous types

The first thing that you need to do is that remove the class. (C# compiler will create the anonymous class based on what you initialize with.) Secondly, we have to change _person variable to implicitly-typed local variable by replacing “Person” with “var”. Because we have removed Person class from our code so that we won’t know about the type. That’s why the variable “_person” should be declared as a implicitly-typed local variable. Then, we will remove “Person” after “new” keyword.

So, our final code will be like that below ~

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1 {
class Program {
static void Main(string[] args) {
var _person = new { ID = 1,
FirstName = "Michael",
LastName = "Sync" };

Console.WriteLine("Name: {0} {1}",
_person.FirstName,
_person.LastName);

Console.ReadLine();
}
}
}

It’s just like using object and collection initializer. but the magic comes at this point. The C# compiler will create the anonymous class based on the initializer in IL. You can’t see/access that class directly from code but you should know there is a class.

Now, I think that you understand what Anonymous types are and how to create them. But there is one important must-known thing left to tell you. Keep in mind that you can create the Anonymous type as the way that I showed above but this is NOT what it is designed for.

Let me share you one nice comment from this link.

I think that perhaps your dislike of C#’s new features stems from the fact that you are looking at the new features and trying to imagine how you would use them within the context of your current programming patterns. However, these new features are designed to be used in completely new ways.

Anonymous types are not meant to be used in places where you would care about their name or method overriding — in those cases you should use a class. Anonymous types are for when you want to just group together a bunch of data items. Perhaps you are running a query that returnsa few arbitrary pieces of data, or maybe you have a function that needs to return multiple pieces of data. Can you imagine what it would be like if you had to create a new class for each different query in an application?

C# 3.0’s new set-based operators (LINQ) give us wonderful new tools for working with data sets. One thing we frequently need is objects which do nothing besides hold data to iterate over. Do you want to define a datatype for every query that returns a different set of columns? Quite frankly, it’s a pain in the butt. It leads to a proliferation of meaningless types, type unsafety (just using objects), or somewhere inbetween (having a bunch of standard types and only filling in whatever data is returned because maintaining the types every time a query changes becomes too much work).

The type proliferation problem is especially bad in Java where each class requires its own file. As a side note, I once wrote a compiler for a language with lexical scoping (like Pascal, where a function could have an inner function that can access the local variables of its outer function). This means that each local variable scope requires its own separate data structure, which would have to have its own separate class file if the compiler were targeting the JVM. What’s the point of having a whole bunch of classes with no methods and every member public?

internal class CustomerName_OrderCount { public string Name; public int Count; }
internal class CustomerName_Country { public string Name; public string Country; }
internal class CustomerName_Country_State_Phone { public string Name; public string Country; public string State; public string Phone; }
internal class CustomerName_Country_State_Phone_OrderCount { public string Name; public string Country; public string State; public string Phone; public int Count; }

I wouldn’t want an unnecessary mess like that cluttering up my code.

Additionally, though, having anonymous types means that the compiler knows that calling the constructor and properties have no side-effects, which allows it to reason about the values in ways it otherwise could not. This is important for being able to translate queries to SQL and know that you’re getting the correct semantics.

I really like this comment and it did explain a lot. Anonymous types are designed for LINQ. If you are very new to LINQ then you might feel those C# 3.0 features are not so cool but once you got that then you will just love them. :)

Let’s take a look the practical way of using Anonymous type with LINQ ~

We have one XML file as following structure and data.

<?xml version="1.0" encoding="utf-8" ?>
<Girls>
<Girl>
<Name>Camilla Belle</Name>
<DateOfBirth>October 2, 1986</DateOfBirth>
</Girl>
<Girl>
<Name>Megan Fox</Name>
<DateOfBirth>May 16, 1986</DateOfBirth>
</Girl>
<Girl>
<Name>Vicki Zhao(Zhao Wei)</Name>
<DateOfBirth>March 12, 1976</DateOfBirth>
</Girl>
<Girl>
<Name>Kelly Hu</Name>
<DateOfBirth>February 13, 1968</DateOfBirth>
</Girl>
<Girl>
<Name>Elisha Cuthbert</Name>
<DateOfBirth>November 30, 1982</DateOfBirth>
</Girl>
<Girl>
<Name>Alicia Silverston</Name>
<DateOfBirth>October 4, 1976</DateOfBirth>
</Girl>
<Girl>
<Name>Christy Chung</Name>
<DateOfBirth>September 19, 1970</DateOfBirth>
</Girl>
</Girls>

You can easily query the data from this XML with the code below. Additionally, you will get the strong-typed variable reference. That means you will see “Name” and “DateOfBirth” as the properties of “Girl” class in intellisense.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
namespace ConsoleApplication1 {
class Program {
static void Main(string[] args) {
XDocument xmlSource = XDocument.Load("Girls.xml");

var girls = from g in xmlSource.Descendants("Girl")
select new
{
Name = g.Element("Name").Value,
DateOfBirth = g.Element("DateOfBirth").Value
};

foreach (var girl in girls) {
Console.WriteLine("Name: {0}, Date Of Birth: {1}",
girl.Name,
girl.DateOfBirth);
}
Console.ReadLine();
}
}
}

Yes. This is what Anonymous type, implicitly-typed variables and object initializer are designed for. They are so powerful and very cool with LINQ. I hope that you now have good understand about what Anonymous type is and how to use it. You should play around with your own scenario or use it in your real project if you have the chance so that you will be more familiar with those new features and will understand more than what I wrote in this tutorial. Good Luck. :)