0. 目錄 C#6 新增特性目錄 1. 老版本的代碼 早C#3中引入的集合初始化器,可是讓我們用上面的語法來在聲明一個字典或者集合的時候立即初始化一些項進去,其實在C#3中這是個語法糖,實質編譯後的結果是調用字典或者集合的Add方法逐一添加這些項。但是有一點小小的不直觀。先看看這個版的IL吧: 本質 ...
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可以是任意類型,凡是有索引器支持的類型,均可以使用這種語法。簡單直接明瞭。