我們在學習C#的時候通常都會多多少少接觸ILDasm和Reflector,這兩樣工具讓我們對C#的理解不會只停留在編譯器這個層面
上,而是讓我們更深入的穿透編譯器。這篇也是希望對IL和Reflector不是很瞭解或者懶的瞭解的同學能夠重視起來,同樣這篇我還是
以QA的形式來告知這兩樣工具的強大和必要性。
Q:介面中只能存在方法嗎?
A: 這個問題,如果你對IL不熟悉的話,你可能會認為是錯的,你可能會天真的認為,記得不錯的話,屬性好像也可以定義在介面中,事
件好像也可以定義在介面中,欄位可不可以就不知道了,好吧,我們看下IL,到底是怎麼樣的。
1 public interface IFly 2 { 3 bool CanFly { get; set; } 4 5 event Action ActionFly; 6 }
然後我們再看看IL,會發現 “屬性” 其實GetXXX/SetXXX方法,“事件”其實就是 Add_XXX/Remove_XXX方法,
當然還有一個 “索引器”,本質上也是 get_Item/set_Item 這個配對方法,看完這三個屬性之後,可能有些人會想來出來還有一個
“建構函式”,本質上它也是方法,但是確不能定義在介面中,當然這個就不是IL的事情的,而是OO定義的問題了,因為介面定義的
目的是規範,而ctor是初始化類,屬於類的一種實現,而介面的規範就是隻能提供方法的定義,不能提供方法的實現,現在我們再看
一下,欄位是否可以定義在介面中?
從截圖中可以清楚的看到,“介面不能包含欄位”的error資訊,好了,到現在我們可以總結一句話就是,介面中只能定義除建構函式
之外的方法,這個例子展示IL對我們分析問題的重要性。
Q:Random.Next為什麼多次New之後,會出現重複?
static void Main(string[] args) { for (int i = 0; i < 1000; i++) { var rand = new Random(); Console.WriteLine(rand.Next()); } Console.Read(); }
A: 這個問題問的好,要想知道為什麼,我們得一定要用Reflector來反編譯下Random類的程式碼,到底裡面是怎麼實現的,要知
其然,還要知其所以然,下面我們來看看反編譯後的程式碼。
從next函式中的定義可以看出,其實return 的num值取決於seedArray,那麼我們下一步看看seedArray到底是怎麼玩起來的。
通過程式碼,我們可以找到其實就是在ctor裡面做的。
我們可以看到這個for迴圈,大概看下程式碼意思,可以看出第一個for是給seedArray灌值,第二個for是取下標就是求餘,然後-=操作
來讓SeedArray中的值更加的混亂,反正大體意思就是SeedArray中的值比較亂,比較隨機,然後我們的next就是通過inext和inextp
取SeedArray值,從而造成隨機數,這個不難看出,隨機的源頭就是我們給過去的Seed值,然後我們看到inext和inextp都是++操作,
所以我們多次next操作之後,這就保證我們取數永遠都是隨機的,而如果源頭的Seed一樣的話,就會導致return的值一直重複。
這次我們把Random放到for迴圈之外再看看,因為inext和inextp是通過++操作來獲取SeedArray的值來儘可能的避免重複。
1 static void Main(string[] args) 2 { 3 var rand = new Random(); 4 5 for (int i = 0; i < 1000; i++) 6 { 7 Console.WriteLine(rand.Next()); 8 } 9 Console.Read(); 10 }
請猛擊視訊教程:http://t.cn/RPtyOFp