終於寫到終結篇了,整個人像在夢游一樣,說完這一篇我得繼續寫我的js系列啦。
一:帶索引的對象初始化器
還是按照江湖老規矩,先扒開看看到底是個什麼玩意。
1 static void Main(string[] args) 2 { 3 Dictionary<string, string> dic = new Dictionary<string, string>() 4 { 5 ["Name"] = "ctrip", 6 ["Age"] = "15" 7 }; 8 }
第一眼看到這個還是蠻新鮮的,不過轉眼就能想到是不是跟數組初始化器,對象初始化器一個樣?你要是這麼想就對了,下面我們來看看這玩意會生成
什麼樣的IL。
從上圖中可以清楚的看到set_Item方法,這個方法就是編譯器上層的索引器語法糖,就是忽悠我們提高開發效率的,不過也還行,起碼讓我少輸入了
兩個dic,然後把代碼還原如下:
1 Dictionary<string, string> dic = new Dictionary<string, string>(); 2 dic["Name"] = "ctrip"; 3 dic["Age"] = "20";
索性趁熱打鐵,看看這個索引器方法的內部代碼是什麼樣的,從下圖中可以看到是一個Insert操作。
二:無參數的結構體構造函數
不知道有多少人知道值類型在C#6.0之前是絕對不可以定義默認構造函數的,為什麼這麼說呢?道理很簡單,因為值類型和引用類型的機制不一樣,
值類型不需要new就可以在棧中分配空間,比如下面的結構體Point,只要我們定義了,就可以方便的使用point.X值。
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 using System.Console; 7 8 namespace ConsoleApplication3 9 { 10 class Program 11 { 12 static void Main(string[] args) 13 { 14 Test t = new Test(); 15 var s = t.point.X; //請問有沒有調用構造函數啊?啊啊啊啊啊。。。。。。。。。。。。。。。 16 Console.Read(); 17 } 18 } 19 20 public class Test 21 { 22 public Point point; 23 } 24 25 public struct Point 26 { 27 public int X; 28 29 public int Y; 30 31 public Point() 32 { 33 X = 5; 34 Y = 5; 35 } 36 } 37 }
如果執行了默認構造函數,那我point.X的時候會輸出5,是不是覺得有點奇怪呢?所以基於這個原因,C#6.0之前為了避嫌,就禁止了這種默認的值
類型構造形式。但是這次在C#6.0中居然放開了,所以我就很迫不及待的去看一看到底調沒調用默認構造函數,如下圖:
從圖中看到並沒有調用默認構造函數,到這裡我也知道了,只有在我new的時候才會調用,所以我就發現,值類型是在模仿引用類型的使用方式了,
個人感覺真的沒有必要放開這個限制。
三:異常篩選器
C#6.0中這個異常篩選器還真是個比較新奇的東西,不看不知道,一看嚇一跳,比如下面的代碼。
1 public void Run() 2 { 3 try 4 { 5 } 6 catch (Exception ex) 7 if (ex.Message.Contains("timeout")) 8 { 9 throw; 10 } 11 }
如果你仔細看的話,好像就是一個catch中省略了{}而已嘛?並沒有看到什麼其他特殊的東西,然後我就非常好奇的把上面的代碼恢復到6.0版本之前,
代碼如下:
1 public void Run1() 2 { 3 try 4 { 5 6 } 7 catch (Exception ex) 8 { 9 if (ex.Message.Contains("timeout")) 10 { 11 throw; 12 } 13 } 14 }
接來下,我們就來看看這兩份代碼的IL到底會是個什麼樣子?內心狂雞凍啊,啊啊啊啊啊啊啊。。。。都痙攣了。。。。。
可以看到,上面兩份貌似相同的代碼,其實生成的IL還是有很大區別的,新版代碼中會用isinst判斷是否為Exception的實例,並且用brtrue來判斷當前是否
為null,如果是null,則不會執行ex.Message.Contains("timeout")語句了。但是老版代碼並沒有true/false判斷,還是按照常規執行,所以現在可以知道,
其實並不是簡單的省略了個"{}"大括號,這個語法糖在底層還是有些智能判斷的。
好了,所有的C#6.0的語法糖分析到這裡就結束了,感謝大家的關注。