C#6 新增特性目錄
1 internal class Person 2 { 3 public string Name { get; set; } 4 public int Age { get; set; } 5 6 public override string ToString() 7 { 8 return string.Format("[name={0},age={1}]", Name, Age); 9 } 10 }
通常我們在格式化字符串的時候會使用string的靜態方法Format來進行字符串拼接,然後使用{0}...{n}來充當占位符。如果{n}過大,代碼的可讀性就會急劇下降,C#6引入一個新語法來簡化這種書寫方式。
我們之間來看新語法:
1 internal class Person 2 { 3 public string Name { get; set; } 4 public int Age { get; set; } 5 6 public override string ToString() 7 { 8 return $"[name={Name},age={Age}]"; 9 } 10 }
新語法采用 $ 開頭,然後把之前的{n}換成了有意義的表達式,直觀且簡潔,且在VS2015中會有智能提示。好了,基本用法就是這樣,按老習慣,對比下IL代碼吧。
老版本的IL:
1 .method public hidebysig virtual instance string 2 ToString() cil managed 3 { 4 // Code size 33 (0x21) 5 .maxstack 3 6 .locals init ([0] string V_0) 7 IL_0000: nop 8 IL_0001: ldstr "[name={0},age={1}]" 9 IL_0006: ldarg.0 10 IL_0007: call instance string csharp6.Person::get_Name() 11 IL_000c: ldarg.0 12 IL_000d: call instance int32 csharp6.Person::get_Age() 13 IL_0012: box [mscorlib]System.Int32 14 IL_0017: call string [mscorlib]System.String::Format(string, 15 object, 16 object) 17 IL_001c: stloc.0 18 IL_001d: br.s IL_001f 19 IL_001f: ldloc.0 20 IL_0020: ret 21 } // end of method Person::ToString
新語法的IL:
1 .method public hidebysig virtual instance string 2 ToString() cil managed 3 { 4 // Code size 33 (0x21) 5 .maxstack 3 6 .locals init ([0] string V_0) 7 IL_0000: nop 8 IL_0001: ldstr "[name={0},age={1}]" 9 IL_0006: ldarg.0 10 IL_0007: call instance string csharp6.Person::get_Name() 11 IL_000c: ldarg.0 12 IL_000d: call instance int32 csharp6.Person::get_Age() 13 IL_0012: box [mscorlib]System.Int32 14 IL_0017: call string [mscorlib]System.String::Format(string, 15 object, 16 object) 17 IL_001c: stloc.0 18 IL_001d: br.s IL_001f 19 IL_001f: ldloc.0 20 IL_0020: ret 21 } // end of method Person::ToString
第一眼看到新版本的IL代碼,我還以為我沒有重新編譯我的代碼。C#編譯器幫我們轉成了老版本的寫法而已,一模一樣的。。。so,這又是一個語法層面的優化。
1 //支持方法調用 2 string s1 = $"{person.GetHashCode()}"; 3 //支持表達式 4 string s2 = $"person.{nameof(person.Name)} is {person?.Name}"; 5 //支持格式化輸出 6 DateTime now = DateTime.Now; 7 string s3 = $"DateTime.Now={now:yyyy-MM-dd HH:mm:ss}"; 8 //組合表達式和格式化輸出 9 string s4 = $"{person.Name,2} is {person.Age:D2} year{(person.Age == 1 ? "" : "s")} old."; 10 //支持的隱式類型轉換 11 IFormattable s5 = $"Hello, {person.Name}"; 12 FormattableString s6 = $"Hello, {person.Name}"
新語法支持表達式求值,支持:格式化操作,還支持到IFormattable的隱式轉換,編譯結果是利用 System.Runtime.CompilerServices.FormattableStringFactory.Create 這個靜態方法構造一個 FormattableString 實現的。IL如下:
1 IL_0095: stloc.s s4 2 IL_0097: ldstr "Hello, {0}" 3 IL_009c: ldc.i4.1 4 IL_009d: newarr[mscorlib] System.Object 5 IL_00a2: dup 6 IL_00a3: ldc.i4.0 7 IL_00a4: ldloc.0 8 IL_00a5: callvirt instance string csharp6.Person::get_Name() 9 IL_00aa: stelem.ref 10 IL_00ab: call class [mscorlib]System.FormattableString[mscorlib] System.Runtime.CompilerServices.FormattableStringFactory::Create(string,object[]) 13 IL_00b0: stloc.s s5 14 IL_00b2: ldstr "Hello, {0}" 15 IL_00b7: ldc.i4.1 16 IL_00b8: newarr[mscorlib] System.Object 17 IL_00bd: dup 18 IL_00be: ldc.i4.0 19 IL_00bf: ldloc.0 20 IL_00c0: callvirt instance string csharp6.Person::get_Name() 21 IL_00c5: stelem.ref 22 IL_00c6: call class [mscorlib]System.FormattableString[mscorlib] System.Runtime.CompilerServices.FormattableStringFactory::Create(string,object[])
Interpolated Strings