在C#3.0中,一个对象创建表达式可以包含一个对象或集合初始化器,用于初 始化新创建的对象的成员或新创建的集合的元素。
对象创建表达式:
new type (argument-list(可选)) 对象或集合初试化器(可选)
new type 对象或集合初试化器
一个对象创建表达式可以省略构造器参数列表,并将其连同圆括号一起替换 为一个对象或集合初始化器。省略构造器参数列表并将其连同圆括号一起替换为 一个对象或集合初始化器等价于指定一个空的参数列表。
在执行一个带有对象或集合初始化器的对象创建表达式时,首先调用实例构 造器,然后执行对象或集合初始化器指定的成员或元素初始化。对象或集合初始 化器不能引用正在初始化的对象实例。
20.4.1 引入对象初始器
在传统的C#中,我们常用两种方法来对一个类(或者结构体)进行初始化, 一是采用带有参数的构造函数,另一种则是不采用构造函数,或者构造函数中并 没有实际地对字段进行赋值,而是在申请了类的实例之后,手动对它的公共属性 进行赋值。下面是一个二维空间的几何点例子:
public class Point
{
private int xPos, yPos;
//缺省的构造函数
public Point()
{
}
public Point(int x, int y)
{
xPos = x;
yPos = y;
}
public int X
{
get { return xPos; }
set { xPos = value; }
}
public int Y
{
get { return yPos; }
set { yPos = value; }
}
public override string ToString()
{
return string.Format("[{0}, {1}]", xPos, yPos);
}
}
对于这个类,按照一般方法,我们会这样来初始化它:
//调用自定义的构造函数
Point p = new Point(100,200);
//或者手动指定每个属性
Point p1 = new Point();
p1.X = 100;
p1.Y = 200;
现在我们采用类初始化器的C# 3.0代码则可以写成下面的样子:
var p1 = new Point { X = 100, Y = 200 };
Point p = new Point { X = 100, Y = 200 };
其中第一个是隐式类型变量。这里并没有显式调用Point的构造函数,仅仅是 将值设给了公共的X和Y属性。在这里,类型的缺省构造函数被调用,紧跟着将值 赋给指定的属性。从这一点上说,最后这两个实例实际上就是第一个实例的简化 写法。
从上面的例子中,我们可以看出:
l 对象初始化器由一系列的成员初始化器构成,包围在{和}记号中,并用逗 号进行分隔。每个成员初始化器以对象的一个可访问的域或属性的名字开始,后 跟一个等号,之后是一个表达式或一个对象或集合初始化器。如果对象初始化其 中包括了对同一个域或属性的多于一个的成员初始化器,将会发生错误。
l 在等号后面指定了表达式的成员初始化器的处理与域和属性的赋值一致。
l 在等号后面指定了对象初始化器的成员初始化器也是对一个嵌套对象的初 始化。与为域或属性赋一个新值不同,对象初始化器中的赋值被视为对域或属性 的成员进行赋值。一个具有值类型的属性不能通过这种构造来进行初始化。
l 在等号后面指定了集合初始化器的成员初始化器也是对一个嵌套集合的初 始化。与为域或属性赋一个新的集合不同,初始化器中给定的元素将被添加到域 或属性所引用的集合中。该域或属性必须是一个满足下一节所指定的需求的集合 类型。
l 对象初时化器是利用了编译器对对象中的对外可见的字段或属性进行按序 赋值,在编译还是隐式调用了构造函数,对字段或属性的赋值可以是一个或是多 个。