集合初始化器

  第5章描述了如何使用如下语法,用值来初始化数组:

  1. int[] myIntArray = new int[5]{ 5, 7, 11, 2, 98 };

  这是一种合并实例化和初始化数组的简捷方式。集合初始化器只是把这个语法扩展到集合上:

  1. List<int> myIntCollection = new List<int> { 5, 7, 11, 2, 98 };

  通过合并对象和集合初始化器,就可以用简洁的代码配置集合了。下面的代码:

  1. List<Curry> curries = new List<Curry>();
  2. curries.Add(new Curry("Chicken", "Pathia", 6));
  3. curries.Add(new Curry("Vegetable", "Korma", 3));
  4. curries.Add(new Curry("Prawn", "Vindaloo", 9));

  可以用如下代码替换:

  1. List<Curry> curries = new List<Curry>
  2. {
  3. new Curry
  4. {
  5. MainIngredient = "Chicken",
  6. Style = "Pathia",
  7. Spiciness = 6
  8. },
  9. new Curry
  10. {
  11. MainIngredient = "Vegetable",
  12. Style = "Korma",
  13. Spiciness = 3
  14. },
  15. new Curry
  16. {
  17. MainIngredient = "Prawn",
  18. Style = "Vindaloo",
  19. Spiciness = 9
  20. }
  21. };

  这非常适合于主要用于数据表示的类型,因此,集合初始化器和本书后面介绍的LINQ技术一起使用时效果极佳。

  下面的示例说明了如何使用对象和集合初始化器。

  1. static void Main(string[] args)
  2. {
  3. Farm<Animal> farm = new Farm<Animal>
  4. {
  5. new Cow { Name = "Norris" },
  6. new Chicken { Name = "Rita" },
  7. new Chicken(),
  8. new SuperCow { Name = "Chesney" }
  9. };
  10. farm.MakeNoises();
  11. Console.ReadKey();
  12. }
  13. public class Farm<T> : IEnumerable<T> where T : Animal
  14. {
  15. public void Add(T animal)
  16. {
  17. animals.Add(animal);
  18. }
  19. ...
  20. }
  示例的说明  这个示例合并了对象和集合初始化器,用一个步骤创建并填充了一个对象集合。它使用前面章节介绍的农场对象集合,但需要对用于这些类的初始化器做两处修改。  首先,给派生于Animal基类的类删除构造函数。可以删除这些构造函数,是因为它们设置了动物的Name属性,而这里使用对象初始化器来完成。另外,还可以添加默认的构造函数。无论采用哪种方式,在使用默认的构造函数时,会根据基类中的默认构造函数来初始化Name属性,代码如下:
  1. public Animal()
  2. {
  3. name = "The animal with no name";
  4. }

  但是,对象初始化器与派生于Animal类的类一起使用时,初始化器设置的任何属性都在对象实例化后设置,因此在执行这个基类的构造函数之后设置。如果Name属性的值作为对象初始化器的一部分提供,这个值就会覆盖默认值。在示例代码中,为添加到集合中的所有项设置了Name属性,只有一项除外。

  其次,必须给Farm类添加Add()方法,否则会得到如下形式的一些列编译错误:

  1. 'Ch14Ex01.Farm<Ch14Ex01.Animal>' does not contain a definition for 'Add'

  这个错误显示出了集合初始化器的部分底层功能。在后台,编译器为在集合初始化器中提供的每一项调用集合的Add()方法。Farm类通过Animals属性提供了一个Animal对象的集合。编译器猜不出这就是要通过Animals.Add()填充的属性,所以代码会失败。为更正这个问题,可以把Add()方法添加到类中,类通过对象初始化器进行初始化。

  还可以修改示例中的代码,为Animals属性提供一个嵌套的初始化器,如下所示:

  1. static void Main(string[] args)
  2. {
  3. Farm<Animal> farm = new Farm<Animal>
  4. {
  5. Animals =
  6. {
  7. new Cow { Name = "Norris" },
  8. new Chicken { Name = "Rita" },
  9. new Chicken(),
  10. new SuperCow { Name = "Chesney" }
  11. }
  12. };
  13. farm.MakeNoises();
  14. Console.ReadKey();
  15. }

  有了此代码,就不需要为Farm类提供Add()方法了。这个技巧适用于包含多个集合的类。这种情况下,用包含类的Add()方法添加的集合没有其他方式。