C# 3.0: I do not like Anonymous types

This is the my fifth post in the series of posts I am making on the new features in C#3.0. See the previous posts on var, extension methodlambda expressions and object-collection initializers

Before getting into why I do not like (actually hate) anonymous types in C#. Let's see what is this anonymous types and whats so special with this anonymity.

Anonymous types

Anonymous type is syntactic sugar to reduce typing. Let's say I need to create a structure or class to contain some data regarding customers. This is how you do it in C# 1.0

 class Customer{    private string name;    public string Name { get { return name; } 
                         set { name = value; }}
     private string address;    public string Address { get { return address; } 
                            set { address = value; } }} Customer cust = new Customer();cust.Name = "Abhinaba Basu";cust.Address = "Hyderabad, India";

Or using the new Object initialization syntax of C#3.0 as

 var cust = new Customer{Name = "Abhinaba Basu", 
                        Address = "Hyderabad, India"};

This is a very repitative code pattern of creating data only containers (class or struct) for the related data types. This is can be done with the Anonymous method syntax as

 var cust1 = new { Name = "Abhinaba Basu", 
                  Address = "Hyderabad, India" };

Note that in this statement I have not named a type and hence the compiler emits code to generate a new class definition whose name is not know to us and hence is a Anonymous type. The following code is generated. 

 public sealed class <Projection>f__0{    // Methods    public <Projection>f__0();    public override bool Equals(object);    public override int GetHashCode();    public override string ToString();    // Properties    public string Address { get; set; }    public string Name { get; set; }    // Fields    private string _Address;    private string _Name;}

Here <Projection>f__0 is the generated class' name. For each member a private field and the corresponding property is generated. The class also generates proper implementation to override Equals, GetHashCode and ToString methods based on each of the fields. The rest of the code is same as that used for Object initialization.

If we have two such declaration that match in the field types then the same class will be used for both of them.

 var cust1 = new { Name = "Abhinaba", Address = "Hyderabad" };var cust2 = new { Name = "Ankur", Address = "Noida"};if (cust1.GetType() == cust2.GetType())    Console.WriteLine("Cust1 and Cust2 are of the same type {0}",                        cust2.GetType().ToString());
// output:// Cust1 and Cust2 are of the same type 
// AnonymousTypes.Program+<Projection>f__0

There are couple of interesting point here

  • The whole thing works only for classes where you do not need to add methods
  • You have to accept the compilers implementaion of the overrides.
  • This works in situation where you are actually not interested to know the name of the generated class
  • All the fields in the class are implicitely typed (var). So the compiler figures out the type to use (Age is Int32)

You can also use nested declaration as in

 var cust = new { Name = "Abhinaba Basu", 
                 Address = "Hyderabad, India",                  Phone =  new  { AreaCode = 33, Number = 444444} };

Why I do not like anonymous types

Again due to my upbringing in C/C++ I did not like implicit types when I saw it. This is taking the same idea to an extreme. Now not only are we letting the compiler choose the type for me I am also letting it generate new types!!!

Even without my pre-disposition I think that this construct address some special programming cases and should not have been included in the language. It'll just add to the surface area and learning curve and mainly go unused. The unusability comes from the following reasons

  • Flexibility is lost. Today I have a data type that has only data and right now I do not care about the exact type. If in the future I need to add some method to it (say to change the Equals override) I need to change all the places where I used the anonymous types and convert them to named types.
  • I decide to add a new field to the class which is used by some of the object and not by some. At the same time I need all of the objects to be of the same type (maybe because I compare them) then I need to go and make changes at all the object allocation code
    var cust = new { Name = "Abhinaba Basu", Address = "Hyderabad, India", phone }
  • Readability of the code is lost. If I have an API like void Show(var value) and I call it as follows
    var cust = new { Name = "foo", Address="bar");
    Show(cust);
    then this does not convey much. The alternative is much more readable when void Show (Customer cust) is defined and used as follows
    Customer cust = new Customer { Name = "foo", Address="bar");
    Show (cust);