一、 引言

C# 3.0中新的对象初始化器是一种简单的语法特征-借助于这种特征,对象的构建和初始化变得非常简单。假定你有一个类Student,它看起来有如下样子:

public class Student{
 public string firstName;
 public string lastName;
}

那么,你可以使用对象初始化器来创建这个类的一个对象,如下所示:

var student1 = new Student{firstName = "Bruce", lastName = "Willis"};

C# 3.0中新的集合初始化器语法也具有类似操作特征。例如,实现System.Collections.Generic.ICollection<T>的任何对象都可以使用一个集合初始化器来初始化它的值。

一个集合初始化器由下列部分组成:

· 一个对象初始化器序列,用"{"和"}"符号包括,并且由逗号隔开。

· 元素初始化器,它们中每一个都指定一个元素以被添加到指定的集合对象中(元素初始化器不能是一个集合初始化器中的赋值表达式)。

那么,究竟它是如何工作的呢?一个集合初始化器必须遵循下列规则:

· 应用集合初始化器的每一个集合对象必须是一种实现了System.Collections.Generic.ICollection<T>的类型(恰好针对一个T)。

· 必须存在从每一个元素初始化器到T类型的一种隐式转换。一个集合初始化器针对每一个指定的元素都会按序调用ICollection<T>.Add(T)方法。

作为一个例子,下面的集合初始化器创建并初始化一个新的字符串集合-这个集合具有3个成员:"Alice","Bob"和"Chris",参考如下:

List<string> names = new List<string> { "Alice", "Bob", "Chris" };

注意:所有的初始值都是字符串类型。否则,你将得到一个编译器错误。

二、 实现集合初始化

假定你想描述一个班及其中的注册同学。为此,你可以通过使用C# 3.0中的集合初始化器编程实现,如下所示:
 
using System;
using System.Collections.Generic;
using System.Text;
using System.Query;
using System.Xml.XLinq;
using System.Data.DLinq;
namespace CollectionInitializer
{
 class Program
 {
  public class MyClass
  {
   public string nameofClass;
   public List<string> studentNames = new List<string>();
  }
  static void Main(string[] args)
  {
   var classes = new List<MyClass>
   {
    new MyClass
    {
     nameofClass = "Science",
     studentNames = {"Laura", "George"}
    },
    new MyClass
    {
     nameofClass = "Commerce",
     studentNames = {"Bill", "Hillary"}
    }
   };
  }
 }
}

如果你有Visual Studio 2005并且安装了LINQ Preview,那么可以在IDE中编译上面的代码。

如果你没有VS 2005但是安装了LINQ Preview,那么你可以使用下列命令来从命令行编译该代码:
 
C:\Program Files\LINQ Preview\Bin\Csc.exe
/reference:"C:\Program Files\LINQ Preview\Bin\System.Data.DLinq.dll"
/reference:C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\System.Data.dll
/reference:C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\System.dll
/reference:"C:\Program Files\LINQ Preview\Bin\System.Query.dll"
/reference:C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\System.Xml.dll
/reference:"C:\Program Files\LINQ Preview\Bin\System.Xml.XLinq.dll" Program.cs

三、 代码剖析

让我们更细致地分析一下前面的C# 3.0代码:

var classes = new List<MyClass>
{
 new MyClass
 {
  nameofClass = "Science",
  studentNames = {"Laura", "George"}
 },
 new MyClass
 {
  nameofClass = "Commerce",
  studentNames = {"Bill", "Hillary"}
 }
};

对于编译器来说,它具有与下面代码相同的效果:
 
var classes = new List<MyClass>();
var __c1 = new MyClass ();
__c1.nameofClass = "Science";
__c1.studentNames.Add("Laura");
__c1.studentNames.Add("George");
classes.Add(__c1);
var __c2 = new MyClass();
__c2.nameofClass = "Commerce";
__c2.studentNames.Add("Bill");
__c2.studentNames.Add("Hillary");
classes.Add(__c2);

如果激活ILDASM并且打开了编译的二进制代码形式,那么你能够看到如图1类似的内容。

图1.示例代码片断的编译的二进制形式

如果你双击在ILDASM中的Main结点,那么你会看到下列代码:
 
.method private hidebysig static void Main(string[] args) cil managed
{
 .entrypoint
 //代码大小 138 (0x8a)
 .maxstack 3
 .locals init ([0] class [mscorlib]System.Collections.Generic.List`1
 <class CollectionInitializer.Program/MyClass>
 classes,
 [1] class [mscorlib]System.Collections.Generic.List`1
 <class CollectionInitializer.Program/MyClass>
 '<tampa>f__0',
 [2] class CollectionInitializer.Program/MyClass
 '<tampa>f__1',
 [3] class CollectionInitializer.Program/MyClass
 '<tampa>f__2')
 IL_0000: nop
 IL_0001: nop
 IL_0002: newobj instance void class [mscorlib]System.Collections.
 Generic.List`1<class CollectionInitializer.
 Program/MyClass>::.ctor()
 IL_0007: stloc.1
 IL_0008: ldloc.1
 IL_0009: nop
 IL_000a: newobj instance void CollectionInitializer.
 Program/MyClass::.ctor()
 IL_000f: stloc.2
 IL_0010: ldloc.2
 IL_0011: ldstr "Science"
 IL_0016: stfld string CollectionInitializer.
 Program/MyClass::nameofClass
 IL_001b: nop
 IL_001c: ldloc.2
 IL_001d: ldfld class [mscorlib]System.Collections.Generic.List`1
 <string> CollectionInitializer.
 Program/MyClass::studentNames
 IL_0022: ldstr "Laura"
 IL_0027: callvirt instance void class [mscorlib]System.
 Collections.Generic.List`1<string>::Add(!0)
 IL_002c: nop
 IL_002d: ldloc.2
 IL_002e: ldfld class [mscorlib]System.Collections.Generic.List`1
 <string> CollectionInitializer.
 Program/MyClass::studentNames
 IL_0033: ldstr "George"
 IL_0038: callvirt instance void class [mscorlib]System.Collections.
 Generic.List`1<string>::Add(!0)
 IL_003d: nop
 IL_003e: nop
 IL_003f: ldloc.2
 IL_0040: nop
 IL_0041: callvirt instance void class [mscorlib]System.Collections.
 Generic.List`1<class CollectionInitializer.
 Program/MyClass>::Add(!0)
 IL_0046: nop
 IL_0047: ldloc.1
 IL_0048: nop
 IL_0049: newobj instance void CollectionInitializer.
 Program/MyClass::.ctor()
 IL_004e: stloc.3
 IL_004f: ldloc.3
 IL_0050: ldstr "Commerce"
 IL_0055: stfld string CollectionInitializer.
 Program/MyClass::nameofClass
 IL_005a: nop
 IL_005b: ldloc.3
 IL_005c: ldfld class [mscorlib]System.Collections.Generic.List`1
 <string> CollectionInitializer.
 Program/MyClass::studentNames
 IL_0061: ldstr "Bill"
 IL_0066: callvirt instance void class [mscorlib]System.Collections.
 Generic.List`1<string>::Add(!0)
 IL_006b: nop
 IL_006c: ldloc.3
 IL_006d: ldfld class [mscorlib]System.Collections.Generic.List`1
 <string> CollectionInitializer.
 Program/MyClass::studentNames
 IL_0072: ldstr "Hillary"
 IL_0077: callvirt instance void class [mscorlib]System.Collections.
 Generic.List`1<string>::Add(!0)
 IL_007c: nop
 IL_007d: nop
 IL_007e: ldloc.3
 IL_007f: nop
 IL_0080: callvirt instance void class [mscorlib]System.Collections.
 Generic.List`1<class CollectionInitializer.
 Program/MyClass>::Add(!0)
 IL_0085: nop
 IL_0086: ldloc.1
 IL_0087: nop
 IL_0088: stloc.0
 IL_0089: ret
} //Program::Main方法结束

四、 小结

从前面的一些代码片断中你可以看到,C# 3.0在语法方面迈出了很大的一步。

集合初始化器,作为C# 3.0新引入的特征之一,提供了一种新的语法来初始化集合对象。这种简单的语法把集合对象的创建和初始化结合到一个步骤中。

C# 创建和初始化集合对象的更多相关文章

  1. redis 系列14 有序集合对象

    一. 有序集合概述 Redis 有序集合对象和集合对象一样也是string类型元素的集合,且不允许重复的成员.不同的是每个元素都会关联一个double类型的分数.redis正是通过分数来为集合中的成员 ...

  2. 《闲扯Redis十一》Redis 有序集合对象底层实现

    一.前言 Redis 提供了5种数据类型:String(字符串).Hash(哈希).List(列表).Set(集合).Zset(有序集合),理解每种数据类型的特点对于redis的开发和运维非常重要. ...

  3. Hive_UDF函数中集合对象初始化的注意事项

    UDF函数中定义的集合对象何时初始化 udf函数放在sql中对某个字段进行处理,那么在底层会创建一个该类的对象,这个对象不断的去调用这个evaluate(...)方法,截图如下:   1.1 如果说对 ...

  4. ue4 NewObject/StaticConstructObject_Internal/StaticAllocateObject/FObjectInitializer:对象创建和初始化

    UObject是一套很复杂的体系,之前读ue3代码时曾分析过其类型系统实现,主要是与UClass间的关系 现在转到ue4,发现那一块其实差不多,于是再重点备忘一下UObject本身的创建和初始化过程 ...

  5. java类的初始化和对象的创建顺序

    学习java编程思想--类的初始化p146 类的加载顺序* 1加载器启动找到 xxx.class文件,通过extends关键字寻找基类,先加载基类* 2类初始化先初始化static成员变量和stati ...

  6. 创建ArrayList集合对象并添加元素

    ArrayListDemo.java import java.util.ArrayList; /* * 为什么出现集合类: * 我们学习的是面向对象编程语言,而面向对象编程语言对事物的描述都是通过对象 ...

  7. Java创建List、Map等集合对象的同时进行赋值操作

    title: Java创建List.Map等集合对象的同时进行赋值操作 date: 2019-11-28 23:25:47 tags: JavaSE categories: JavaSE 问题简介   ...

  8. JS中集合对象(Array、Map、Set)及类数组对象的使用与对比

    原文地址 在使用js编程的时候,常常会用到集合对象,集合对象其实是一种泛型,在js中没有明确的规定其内元素的类型,但在强类型语言譬如Java中泛型强制要求指定类型. ES6引入了iterable类型, ...

  9. 初始化集合的花样new HashMap<String, String>{ {put("str1":"abc");} }(转)

    Map集合的普通初始化方法: Map<String, String> map = new HashMap<String, String>(); map.put("Na ...

随机推荐

  1. PAT天梯赛L3-005 垃圾箱分布

    题目链接:点击打开链接 大家倒垃圾的时候,都希望垃圾箱距离自己比较近,但是谁都不愿意守着垃圾箱住.所以垃圾箱的位置必须选在到所有居民点的最短距离最长的地方,同时还要保证每个居民点都在距离它一个不太远的 ...

  2. php类内方法使用类外变量和类外函数

    如果要调用另一个类的属性和方法,直接实例化后调用就可以 但是要使用的变量和函数是独立的,不在本类或其他类里面,这时调用就要用下面的方法(本例是在同一个php文件里,如果不再同一个类文件可以requir ...

  3. elasticsearch常用工具及使用

    1. 数据库工具:https://github.com/jprante/elasticsearch-jdbc 2.数据展示:https://github.com/mobz/elasticsearch- ...

  4. Nginx停止服务和各种命令

    1.停止Nginx服务的四种方法 从容停止服务这种方法较stop相比就比较温和一些了,需要进程完成当前工作后再停止. nginx -s quit 立即停止服务这种方法比较强硬,无论进程是否在工作,都直 ...

  5. 学习:数学----gcd及扩展gcd

    gcd及扩展gcd可以用来求两个数的最大公因数,扩展gcd甚至可以用来求一次不定方程ax+by=c的解   辗转相除法与gcd 假设有两个数a与b,现在要求a与b的最大公因数,我们可以设 a=b*q+ ...

  6. BZOJ1816(二分)

    反思 由于受我第一次遇到的构造最多三角形的题的影响,这种几个分成一组最多多少组的题我老是往贪心上想. 事实上一般贪心也能贪,但这道题,还有突然想起的前些天做的cf140C,都是用二分可以更简单地解决, ...

  7. Uva1608

    如果一个序列的所有子序列中均存在至少一个元素,这个元素在该子序列中只出现一次,则这个序列non-boring. 当一个序列[x,y]中没有元素只出现一次,那么该序列不符合要求,如果有的话,设为第i个元 ...

  8. 读取properties和xml中配置文件的值

    五种方式让你在java中读取properties文件内容不再是难题 在java中读取properties和xml文件中的方法:https://www.cnblogs.com/ConfidentLiu/ ...

  9. Spark操作

    ### scala源码 /* SimpleApp.scala */ import org.apache.spark.SparkContext import org.apache.spark.Spark ...

  10. ubuntu查看系统版本和内核版本

    查看系统版本: cat /etc/issue sudo lsb_release -a 查看内核版本: uname -r