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
- The Constructor will takes arguments to initialize the fields backing the public properties on the anonymous type
- The default Constructor will be removed.
- The public properties will only have getters and no setters
- The name of the parameters for the constructor will be the same as the public propertes.
- 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.
- 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).
Comments
Anonymous
April 13, 2007
The comment has been removedAnonymous
April 15, 2007
The decision seems smart to me. Could you expand more on why you've only now decided to make this decision instead of earlier? Could you also explain any performance implications of this decision?Anonymous
April 17, 2007
The comment has been removedAnonymous
April 17, 2007
I think the simple reason we did not do this early is probably because we did not foresee all the issues, and there are always requests from customer to do interesting with anonymous types :). The Performace implication is are that
- Its a single call (ctor) instead of ctor and initializers.
- Possible limitation on the number of arguments that a constructor can take ... none discovered.
Anonymous
April 21, 2007
Visual Studio Orcas Beta 1 is available for download . Though quite similar to the March CTP in termsAnonymous
April 23, 2007
Hello, I was wondering wether the immutable new anonymous type has a constructor with the same anonymous type as an argument. Like: var v = new { A = 5, b = "bar" }; var v1 = new {v} Which should translate to: var v = new AnonymousType<int, string>(5,"bar"); var v1 = new AnonymousType<int,string>(v); So that the anonymousType class has a constructor with the same anonymousType as an argument.Anonymous
April 23, 2007
To clearyfy my last remark: The AnonymousType<int,string> defined by specifying/inferring the types and names of its parameters. Does this type also has a constructor with a single argument of type AnonymousType<int,string> like so class AnonymousType<int,string>{ private int _a; private string _s; public AnonymousType(int a,string s){ _a=a; _s=s; } public AnonymousType( AnonymousType<int,string> source){ _a=source._a; _s=source._s; } ... other members ... } }Anonymous
April 24, 2007
There are no current plans to have copy constructor for the Anonymous Types. Could you explain the reasoning behind this. Since the Instance are immutable having a copy does not buy much. Creating another instance of the anonymous types which is a copy involves knowing the names/values/order of the arguments, these should be avaiable if the new instance is created in the same method as the first. var v = new { A = 5, b = "bar" }; var v1 = new { A = 5, b = "bar" }; v.Equals(v1); Anonymous types escape functions only as type "System.Object".Anonymous
May 11, 2007
Paul Vick posted that anonymous types will remain mutable in VB . Generally this looks good, I just hopeAnonymous
May 12, 2007
After reading Paul Vick's post, I'm not sure whether anonymous types will be mutable or not. Could clear this up, please? http://www.panopticoncentral.net/archive/2007/05/11/20566.aspxAnonymous
May 14, 2007
Ho sempre sostenuto che VB.NET fosse un linguaggio creato più per ragioni di mercato che per reali necessitàAnonymous
September 12, 2007
Immutable anonymous types are now implemented in DB_Linq - a LINQ provider for MySql, Oracle and PostgresAnonymous
November 29, 2007
Overview In the last article I covered the "results view" for lazy evaluated collections likeAnonymous
June 05, 2008
你是如何创建属性的? 如果你长期使用C#,相信你不会对属性这个东西感到陌生。一般地,属性是对私有字段的一个简单包装,就像这样: 代码1 使用属性而不是直接公开私有字段的一个好处就是...Anonymous
June 06, 2008
转自:http://allenlooplee.cnblogs.com/ 缘起 每次有新技术发布时,我们总能感受到两种截然不同的情绪:一种是恐惧和抵抗,伴随着这种情绪的还有诸如Anonymous
July 01, 2008
缘起 每次有新技术发布时,我们总能感受到两种截然不同的情绪: 一种是恐惧和抵抗,伴随着这种情绪的还有诸如Anonymous
September 22, 2008
每次有新技术发布时,我们总能感受到两种截然不同的情绪: 一种是恐惧和抵抗,伴随着这种情绪的还有诸如Anonymous
March 27, 2009
文章出处:http://www.cnblogs.com/allenlooplee/archive/2008/06/01/1211520.html 缘起 每次有新技术发布时,我们总能感受到两种截然...Anonymous
February 04, 2016
Seems to me the readonly keyword should be used to mark the anonymous type immutable and leave it up to the programmer whether they wanted that or not