Immutable is, the new Anonymous Type

Overview

In the spirit of keeping my first post short and simple, i plan to write about changes to Anonymous tyes that will be of interest to quite a few developers. Anonymous types are immutable, yes its true. Now depending on your current project, prevaling point of view or things you would have read this might seem to be a good or bad thing for you. I will try and throw some light on why this is done and what the change is. Before we begin, In a quick seach on live i found many posts on Anonymous types and If you want to know, what Anonymous types are ? or how to use them ? I would recommend WesDyer's blog.

Since anonymous type's equality and hashcode sematics are defined by its structure ( name, type and order of members) making them immutable has interesting benefits of making the hashcode perform like a well behaved .Net type. That is the hashcode of the object does not change over its lifetime. And since the equality operator can be written to use hashcode, it benefits too, while still maintaining equality based on the structure of the Anonymous Type.

In order to understand this better let's have a look at the GetHashCode Function, which compute the hash by doing the below computation for every member

hash += hash * change + (field ==

null ? 0 : EqualityComparer<T>.Default.GetHashCode(fieldMember))

Therefore by ensuring that the members do not change, we ensure that the hash is constant for the lifetime of the object.This allows anonymous types to be used with collections like hashtables, without actually loosing them when the members are modified. There are a lot of benefits of immutabilty in that, it drastically simplifies the code that uses the object since they can only be assigned values when created and then just used (think threading). It also scopes out the feature for the primary purpose that it is designed, the definition of composite keys in Queries where equality based on structure and selecting projections from the results of a Query.

eg of join between 2 composite keys that have a common structure

from p in products // A composite key equality

join sl in shoppingList on new {p.Name, p.Category} equals new {sl.ItemName, sl.Cat}

select p;

or creating projections from the results sequence.

from p in products

where p.UnitPrice >= 100

select new { Name = p.Name, Price = p.UnitPrice }; //or creating projections from the results sequence.

The Bottom line: So what's the result of these changes on the structure of Anonymous types

  1. The Constructor will takes arguments to initialize the fields backing the public properties on the anonymous type 
  2. The default Constructor will be removed.
  3. The public properties will only have getters and no setters
  4. The name of the parameters for the constructor will be the same as the public propertes.
  5. Anonymous type construction will no longer be realized as an Object initalizer (since the anonymous type is created in a single call), but as a single constructor call.
  6. The fields are readonly.

Anonymous types construction can generate IL to be executed or an Expression Tree which can then be translated.

IL Changes

Each Anonymous Type now has a constructor that accepts the values assigned to each member on the type as arguments. The Parameter (name & type) will match the Property (name & type) on the type. As an example, consider
var v = new { A = 5, b = "bar" };

will result in constructor like public AnonymousType(TypeParameter1 A, TypeParameter2 b); // notice the param A matches property A
and properties like
public TypeParameter1 A { get; } //property A is readonly
public TypeParameter2 b { get; }

and used as
var v = new AnonymousType<int, string>(5, "bar");

Further 2 instantiations of a anonymous-type using the same name & types in the same order, will automatically map to the same generic type. Though this is nothing new and has little to do with immutability I thought I mention it for completeness.

var v = new { A = 5, b = "bar" }; var v1 = new { A = 10, b = "Sree" };

will result in
var v = new AnonymousType<int, string>(5, "bar");
var v1 = new AnonymousType<int, string>(10, "Sree");

Expression Tree

There are 2 new overloads for the "New" method added to Expression tree API that support representing anonymous types. They are ...

public static NewExpression New(ConstructorInfo constructor, IEnumerable<Expression> arguments, IEnumerable<MemberInfo> members)

public static NewExpression New(ConstructorInfo constructor, IEnumerable<Expression> arguments, params MemberInfo[] members)

they create and return the NewExpression object which is used to represent this Anonymous type construction as data (the changes to NewExpression class are shown below). The NewExpression class now has a members collection, this corresponds to the list of members that the arguments should be asigned to, below are some of the changes to the NewExpression class.

public sealed class NewExpression : Expression {

    ReadOnlyCollection<MemberInfo> members;

  public ReadOnlyCollection<MemberInfo> Members{

            get { return this.members; }

        }

}

The C# compiler also uses these overloads when it rewrites an anonymus type as an expression tree, this typically happens when creating queries for IQueryable like

string s = "Hello Anonymous types";

var query = from c in s.AsQueryable()

           select new { ASCII = (int)c };

The Compiler passes in the property getters in the member’s collection, Dlinq uses this expression tree to do its translation and every one is happy.

So when will this be avaiable ?

These changes to the compiler and the System.Core should be publically avaiable in Beta 2.

I would love to hear if you found this information usefull and things i could do to present this material better. (too much code, too little code.. more pictures etc).