0. 目录
1. 老版本的代码
1 private static void Main() 2 { 3 var dictionary = new Dictionary<int, string> { 4 { 1, "Value1" }, 5 { 2, "Value2" }, 6 { 3, "Value3" } 7 }; 8 }
早C#3中引入的集合初始化器,可是让我们用上面的语法来在声明一个字典或者集合的时候立即初始化一些项进去,其实在C#3中这是个语法糖,实质编译后的结果是调用字典或者集合的Add方法逐一添加这些项。但是有一点小小的不直观。先看看这个版的IL吧:
1 .method private hidebysig static void Main() cil managed 2 { 3 .entrypoint 4 // Code size 47 (0x2f) 5 .maxstack 4 6 .locals init ([0] class [mscorlib]System.Collections.Generic.Dictionary`2<int32,string> dictionary) 7 IL_0000: nop 8 IL_0001: newobj instance void class [mscorlib]System.Collections.Generic.Dictionary`2<int32,string>::.ctor() 9 IL_0006: dup 10 IL_0007: ldc.i4.1 11 IL_0008: ldstr "Value1" 12 IL_000d: callvirt instance void class [mscorlib]System.Collections.Generic.Dictionary`2<int32,string>::Add(!0, 13 !1) 14 IL_0012: nop 15 IL_0013: dup 16 IL_0014: ldc.i4.2 17 IL_0015: ldstr "Value2" 18 IL_001a: callvirt instance void class [mscorlib]System.Collections.Generic.Dictionary`2<int32,string>::Add(!0, 19 !1) 20 IL_001f: nop 21 IL_0020: dup 22 IL_0021: ldc.i4.3 23 IL_0022: ldstr "Value3" 24 IL_0027: callvirt instance void class [mscorlib]System.Collections.Generic.Dictionary`2<int32,string>::Add(!0, 25 !1) 26 IL_002c: nop 27 IL_002d: stloc.0 28 IL_002e: ret 29 } // end of method Program::Main
本质是Add方法的调用.C#6引入了一种新语法来进一步的优化这种写法。
2. 索引初始化器
1 private static void Main() 2 { 3 var dictionary = new Dictionary<int, string> 4 { 5 [1] = "Value1", 6 [2] = "Value2", 7 [3] = "Value3" 8 }; 9 }
看起来直观许多了吧,其实是一种语法改进。编译结果也有些许差异,如下:
1 .method private hidebysig static void Main() cil managed 2 { 3 .entrypoint 4 // Code size 47 (0x2f) 5 .maxstack 4 6 .locals init ([0] class [mscorlib]System.Collections.Generic.Dictionary`2<int32,string> dictionary) 7 IL_0000: nop 8 IL_0001: newobj instance void class [mscorlib]System.Collections.Generic.Dictionary`2<int32,string>::.ctor() 9 IL_0006: dup 10 IL_0007: ldc.i4.1 11 IL_0008: ldstr "Value1" 12 IL_000d: callvirt instance void class [mscorlib]System.Collections.Generic.Dictionary`2<int32,string>::set_Item(!0, 13 !1) 14 IL_0012: nop 15 IL_0013: dup 16 IL_0014: ldc.i4.2 17 IL_0015: ldstr "Value2" 18 IL_001a: callvirt instance void class [mscorlib]System.Collections.Generic.Dictionary`2<int32,string>::set_Item(!0, 19 !1) 20 IL_001f: nop 21 IL_0020: dup 22 IL_0021: ldc.i4.3 23 IL_0022: ldstr "Value3" 24 IL_0027: callvirt instance void class [mscorlib]System.Collections.Generic.Dictionary`2<int32,string>::set_Item(!0, 25 !1) 26 IL_002c: nop 27 IL_002d: stloc.0 28 IL_002e: ret 29 } // end of method Program::Main
主要差异在于老语法是调用Add方法,新语法是用的索引器的set访问器(set_Item)。
既然是索引,那么就索引就不仅仅只能是int,也可以是string,任意的自定义类型。
3. Example
namespace csharp6 { internal class Program { public class Person { public string Name { get; set; } public int Age { get; set; } private Dictionary<string, Address> _cache = new Dictionary<string, Address>(); public Address this[string name] { get { return _cache[name]; } set { _cache[name] = value; } } } public class Address { public string Name { get; set; } public string Zip { get; set; } } private static void Main() { //string索引 var colorMap = new Dictionary<string, ConsoleColor> { ["Error"] = ConsoleColor.Red, ["Information"] = ConsoleColor.Yellow, ["Verbose"] = ConsoleColor.White }; //枚举索引 var colors = new Dictionary<ConsoleColor, string> { [ConsoleColor.Red] = "#F00", [ConsoleColor.Green] = "#0F0", }; //自定义类型的索引器支持 Person person = new Person { Name = "blackheart", Age = 1, ["home"] = new Address { Name = "北京市", Zip = "100000" }, ["work"] = new Address { Name = "南京市", Zip = "200000" } }; //自定义类型索引 var persons = new Dictionary<Person, List<Address>> { [new Person { Name = "blackheart", Age = 1 }] = new List<Address> { new Address { Name = "北京市", Zip = "100000" } }, [new Person { Name = "blackheart", Age = 1 }] = new List<Address> { new Address { Name = "南京市", Zip = "200000" } }, }; } } }
4. 总结
从本质来看,[xxx]=yyy这种语法,xxx可以是任意类型,凡是有索引器支持的类型,均可以使用这种语法。简单直接明了。