public class Person
{
public string FirstName {set; get;}
public string LastName {set; get;}
public int Age;
}
以前对Person类成员赋值的过程是这样的:
Person person = new Person();
person.FirstName = "Jack";
person.LastName = "li";
person.Age = 11;
利用object initializer的新特性,可以将以上实现过程写成
Person person = new Person() {FirstName = "Jack", LastName = "li", Age = 11};
可以进一步写成
Person person = new Person {FirstName = "Jack", LastName = "li", Age = 11};
这个代码生成的IL是第一个生成的IL执行过程是一样的。这就可以简化我们的代码,让本来几行才能写完的代码一行写完。
为了更好的掌握object initializer,以下几点需要注意:
1.对象初始化器可以只给部分成员赋值么,赋值时不分先后顺序;
2.对旬初始化只能对public, internal类型的属性数据成员赋值;
3:对象初始化器是否可以结合构造函数一起使用, 构造函数先执行。
Collection Initializers
明白了对象初始化器,就比较好明白集合初始化器,如
var strList = new List<string>{"a", "b"}
var persons = new List<Person>
{
new Person{FirstName="yang"},
new Person{LastName="peng"}
}
集合初始化构造器中可以构造集合的一项为空值.
var persons = new List<Person>
{
new Person{FirstName="yang"},
null;
new Person{LastName="peng"}
}
任何东西都不是完美的,初始化构造器也是有利有弊。最大的好处是和linq结合,可以将linq写得比较简洁。我认为不好的地方是set property对外暴露了接口,如果只是初始化一次,构造函数就可以胜任这个工作,而且具有更好的封装性。另一点需要注意的是对象初始化并不是一定要求数据成员实现set property,有些情况下get也是可以的。看下面这个例子:
public class Contact
{
private List<string> names= new List<string>{"first"};
public List<string> Names
{
get { return names; }
}
}
var contact = new Contact{ Names = {"second"}};
这个Names就是执行的get操作,相当于是contact.Names.Add("second");在这个例子中也暴露出一个问题:当内部数据成员IEnumerable时,不要通过get方式直接返回该成员,这是很不安全的。因为外部得到该成员后,一旦修改,相当于就是直接修改类成员。这破坏了数据的封装性。
任何新事物都是一把双刃剑,关键取决于使用的人。只有对新特性了如指掌,才可以游刃有余地恰当使用。