Saturday, January 30, 2010

Object and Collection Initializers

An object creation expression (§7.5.10.1) may include an object or collection initializer that initializes the members of the newly created object or the elements of the newly created collection.
object-creation-expression:
new   type   (   argument-listopt   )   object-or-collection-initializeropt 
new   type   object-or-collection-initializer
object-or-collection-initializer:
object-initializer
collection-initializer
An object creation expression can omit the constructor argument list and enclosing parentheses, provided it includes an object or collection initializer. Omitting the constructor argument list and enclosing parentheses is equivalent to specifying an empty argument list.
Execution of an object creation expression that includes an object or collection initializer consists of first invoking the instance constructor and then performing the member or element initializations specified by the object or collection initializer.
It is not possible for an object or collection initializer to refer to the object instance being initialized.

Object Initializers

An object initializer specifies values for one or more fields or properties of an object.
object-initializer:
{   member-initializer-listopt   }
{   member-initializer-list   ,   }
member-initializer-list:
member-initializer
member-initializer-list   ,   member-initializer
member-initializer:
identifier   =   initializer-value
initializer-value:
expression
object-or-collection-initializer
An object initializer consists of a sequence of member initializers, enclosed by { and } tokens and separated by commas. Each member initializer must name an accessible field or property of the object being initialized, followed by an equals sign and an expression or an object or collection initializer. It is an error for an object initializer to include more than one member initializer for the same field or property.
A member initializer that specifies an expression after the equals sign is processed in the same way as an assignment (§7.13.1) to the field or property.
A member initializer that specifies an object initializer after the equals sign is an initialization of an embedded object. Instead of assigning a new value to the field or property, the assignments in the object initializer are treated as assignments to members of the field or property. A property of a value type cannot be initialized using this construct.
A member initializer that specifies a collection initializer after the equals sign is an initialization of an embedded collection. Instead of assigning a new collection to the field or property, the elements given in the initializer are added to the collection referenced by the field or property. The field or property must be of a collection type that satisfies the requirements specified in §26.4.2.
The following class represents a point with two coordinates:
public class Point
{
   int x, y;
   public int X { get { return x; } set { x = value; } }
   public int Y { get { return y; } set { y = value; } }
}
An instance of Point can be created an initialized as follows:
var a = new Point { X = 0, Y = 1 };
which has the same effect as
var a = new Point();
a.X = 0;
a.Y = 1;
The following class represents a rectangle created from two points:
public class Rectangle
{
   Point p1, p2;
   public Point P1 { get { return p1; } set { p1 = value; } }
   public Point P2 { get { return p2; } set { p2 = value; } }
}
An instance of Rectangle can be created and initialized as follows:
var r = new Rectangle {
   P1 = new Point { X = 0, Y = 1 },
   P2 = new Point { X = 2, Y = 3 }
};
which has the same effect as
var r = new Rectangle();
var __p1 = new Point();
__p1.X = 0;
__p1.Y = 1;
r.P1 = __p1;
var __p2 = new Point();
__p2.X = 2;
__p2.Y = 3;
r.P2 = __p2;
where __p1 and __p2 are temporary variables that are otherwise invisible and inaccessible.
If Rectangle's constructor allocates the two embedded Point instances
public class Rectangle
{
   Point p1 = new Point();
   Point p2 = new Point();
   public Point P1 { get { return p1; } }
   public Point P2 { get { return p2; } }
}
the following construct can be used to initialize the embedded Point instances instead of assigning new instances:
var r = new Rectangle {
   P1 = { X = 0, Y = 1 },
   P2 = { X = 2, Y = 3 }
};
which has the same effect as
var r = new Rectangle();
r.P1.X = 0;
r.P1.Y = 1;
r.P2.X = 2;
r.P2.Y = 3;

Collection Initializers

A collection initializer specifies the elements of a collection.
collection-initializer:
{   element-initializer-listopt   }
{   element-initializer-list   ,   }
element-initializer-list:
element-initializer
element-initializer-list   ,   element-initializer
element-initializer:
non-assignment-expression
A collection initializer consists of a sequence of element initializers, enclosed by { and } tokens and separated by commas. Each element initializer specifies an element to be added to the collection object being initialized. To avoid ambiguity with member initializers, element initializers cannot be assignment expressions. The non-assignment-expression production is defined in §26.3.
The following is an example of an object creation expression that includes a collection initializer:
List digits = new List { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
The collection object to which a collection initializer is applied must be of a type that implements System.Collections.Generic.ICollection for exactly one T. Furthermore, an implicit conversion (§6.1) must exist from the type of each element initializer to T. A compile-time error occurs if these requirements are not satisfied. A collection initializer invokes the ICollection.Add(T) method for each specified element in order.
The following class represents a contact with a name and a list of phone numbers:
public class Contact
{
   string name;
   List phoneNumbers = new List();
   public string Name { get { return name; } set { name = value; } }
   public List PhoneNumbers { get { return phoneNumbers; } }
}
A List can be created and initialized as follows:
var contacts = new List {
   new Contact {
      Name = "Chris Smith",
      PhoneNumbers = { "206-555-0101", "425-882-8080" }
   },
   new Contact {
      Name = "Bob Harris",
      PhoneNumbers = { "650-555-0199" }
   }
};
which has the same effect as
var contacts = new List();
var __c1 = new Contact();
__c1.Name = "Chris Smith";
__c1.PhoneNumbers.Add("206-555-0101");
__c1.PhoneNumbers.Add("425-882-8080");
contacts.Add(__c1);
var __c2 = new Contact();
__c2.Name = "Bob Harris";
__c2.PhoneNumbers.Add("650-555-0199");
contacts.Add(__c2);
where __c1 and __c2 are temporary variables that are otherwise invisible and inaccessible.

No comments:

Post a Comment