今天在学习Mvc的时候,遇到一种这样的写法
var dic = new ViewDataDictionary { {"ID","1"},{"ProductName","Chai"}};
编译通过并且能够运行,得到元素个数2。发现和平时常用的集合初始化器用法不相同,不知道其中的所以然,这种键值对应的数据结构貌似还有HashTable
System.Collections.Hashtable ht = new System.Collections.Hashtable { {"a","1"}};
居然也可以,又和常用的集合初始化器对比了一番。
public class Car { public int ID { get; set; } public string CarName { get; set; } } ... List<Car> list = new List<Car> { new Car{ID=1,CarName="Benz"}, new Car{ID=2,CarName="BMW"} }; ...
两个的写法差异很明显,实在猜不出,想起了一句话,科学面前来不得马虎,于是用MSIL看看到底怎么回事
... IL_0000: nop IL_0001: newobj instance void [mscorlib]System.Collections.Hashtable::.ctor() IL_0006: stloc.1 IL_0007: ldloc.1 IL_0008: ldstr "a" IL_000d: ldstr "1" IL_0012: callvirt instance void [mscorlib]System.Collections.Hashtable::Add(object, object) ...
第一步,创建hashtable的实例,调用默认的构造函数;
第二部,调用虚方法Add(object,object),将key:"a"与Value:"1"作为参数传递
这里如果不使用{"a","1"}中的花括号,在编译时,错误信息为"Add方法不包含一个参数的重载方法",推断出不使用花括号,编译器认为添加了2个元素
有点想法了,继续写
System.Collections.Hashtable ht = new System.Collections.Hashtable { {"a","1"},{"b","2"}};
如上,集合添加2个元素,每个元素包含2个参数,IL中调用Add方法时,参数匹配
问题清楚了。
继续思考,HashTable,ViewDataDictionary,List<T>等都实现了ICollection<T>的Add方法,集合初始化器是否都能这样写呢?
以 Dictionary<TKey, TValue>类为例子,Add方法如下
public void Add(TKey key, TValue value);
Dictionary<string, Car> d = new Dictionary<string, Car> { {"1",new Car{ID=1,CarName="Benz"}}, {"2",new Car{ID=1,CarName="BMW"}} };
通过!!