Saturday, January 30, 2010

Anonymous Types

C# 3.0 permits the new operator to be used with an anonymous object initializer to create an object of an anonymous type.
primary-no-array-creation-expression:
...
anonymous-object-creation-expression
anonymous-object-creation-expression:
new   anonymous-object-initializer
anonymous-object-initializer:
{   member-declarator-listopt   }
{   member-declarator-list   ,   }
member-declarator-list:
member-declarator
member-declarator-list   ,   member-declarator
member-declarator:
simple-name
member-access
identifier   =   expression
An anonymous object initializer declares an anonymous type and returns an instance of that type. An anonymous type is a nameless class type that inherits directly from object. The members of an anonymous type are a sequence of read/write properties inferred from the object initializer(s) used to create instances of the type. Specifically, an anonymous object initializer of the form
new { p1 = e1 , p2 = e2 , ... pn = en }
declares an anonymous type of the form
class __Anonymous1
{
   private T1 f1 ;
   private T2 f2 ;
   ...
   private Tn fn ;
   public T1 p1 { get { return f1 ; } set { f1 = value ; } }
   public T2 p2 { get { return f2 ; } set { f2 = value ; } }
   ...
   public T1 p1 { get { return f1 ; } set { f1 = value ; } }
}
where each Tx is the type of the corresponding expression ex. It is a compile-time error for an expression in an anonymous object initializer to be of the null type.
The name of an anonymous type is automatically generated by the compiler and cannot be referenced in program text.
Within the same program, two anonymous object initializers that specify a sequence of properties of the same names and types in the same order will produce instances of the same anonymous type. (This definition includes the order of the properties because it is observable and material in certain circumstances, such as reflection.)
In the example
var p1 = new { Name = "Lawnmower", Price = 495.00 };
var p2 = new { Name = "Shovel", Price = 26.95 };
p1 = p2;
the assignment on the last line is permitted because p1 and p2 are of the same anonymous type.
A member declarator can be abbreviated to a simple name (§7.5.2) or a member access (§7.5.4). This is called a projection initializer and is shorthand for a declaration of and assignment to a property with the same name. Specifically, member declarators of the forms
identifier                        expr . identifier
are precisely equivalent to the following, respectively:
identifer = identifier               identifier = expr . identifier
Thus, in a projection initializer the identifier selects both the value and the field or property to which the value is assigned. Intuitively, a projection initializer projects not just a value, but also the name of the value.

No comments:

Post a Comment