CLR via C# 之管中窥豹(一)
記得剛畢業(yè)那會,看過一陣CLR via C#,由于書中知識對于我來說過于深奧,最終只得放棄。而今重新拾起此書并結(jié)合工作中的一些經(jīng)驗,偶有小感就寫成隨筆分享給大家,便于共同探討,也能幫助我成長。
執(zhí)行程序集的代碼
前幾天組里有個測試找我?guī)退麄兛磦€自動化測試的用例,該用例從某一天就一直拋出加載程序集失敗的異常。在這里我用一個場景去模擬當(dāng)時的情形 ,有這么一個測試用例:我們測試Visual Studio創(chuàng)建工程(隨機創(chuàng)建Silverlight或者WPF),并為新建的工程添加一個按鈕。我們需要為WPF和Silverlight創(chuàng)建相應(yīng)的按鈕,但是我們把這兩種按鈕添加的邏輯放到一個方法里面,并通過一個布爾值去區(qū)分不同的工程。添加按鈕邏輯的樣例代碼如下:
1 public void AddButton(bool isSiverlight) 2 { 3 if (isSiverlight) 4 { 5 Silverlight.System.Windows.Controls.Button button = new Silverlight.System.Windows.Controls.Button(); 6 } 7 else 8 { 9 System.Windows.Controls.Button button = new System.Windows.Controls.Button(); 10 } 11 }產(chǎn)品以前有個功能,當(dāng)需要用到一些沒有加載的程序集時,產(chǎn)品根據(jù)一些邏輯找到該程序集但是并不管該程序集是否運行的工程有關(guān)。但是現(xiàn)在改成了只會查找和加載和當(dāng)前工程相關(guān)的程序集。也就是說對于WPF的工程來說,產(chǎn)品不會再去查找或者加載Silverlight的程序集。因此現(xiàn)在在WPF工程中執(zhí)行AddButton方法時,會因找不到Silverlight程序集拋出“Could not load file or assembly 'System.Windows, Version=5.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e' or one of its dependencies”(注:此程序集不在GAC中,也不是Copy Local的)。找到了原因之后,我將AddButton的邏輯稍作改動如下:
1 public void AddButtonUsingSeperateMethod(bool isSiverlight) 2 { 3 if (isSiverlight) 4 { 5 this.AddSiverlightButton(); 6 } 7 else 8 { 9 this.AddWpfButton(); 10 } 11 } 12 13 private void AddSiverlightButton() 14 { 15 Silverlight.System.Windows.Controls.Button button = new Silverlight.System.Windows.Controls.Button(); 16 } 17 18 private void AddWpfButton() 19 { 20 System.Windows.Controls.Button button = new System.Windows.Controls.Button(); 21 }我將AddButton里的方法抽成了兩個獨立的方法,該用例便正常了。測試覺得很奇怪,問我為什么寫成兩個獨立的方法就可以,而獨立的方法便會有異常,邏輯明明是一樣的啊。我于是把CLR via C#找出來,找到“執(zhí)行程序集代碼”的章節(jié)跟他解釋了一番,他便明白了其中的原因。
CLR第一次執(zhí)行到某個方法時,JIT編譯器會將該方法的IL轉(zhuǎn)換成本地CPU指令(步驟參見下圖,來自CLR via C#)。因此當(dāng)執(zhí)行AddButton方法時,會將里面的IL代碼全部解釋為CPU指令,當(dāng)轉(zhuǎn)換"Silverlight.System.Windows.Controls.Button button = new Silverlight.System.Windows.Controls.Button();"時,會需要加載定義該類的程序集查找該類的信息,由于找不到該程序集便有異常發(fā)生了。但是AddButtonUsingSeperateMethod就不一樣了,由于此時是WPF工程,JIT在轉(zhuǎn)換AddButtonUsingSeperateMethod時并不立即將AddSiverlightButton這個方法的具體實現(xiàn)也一并轉(zhuǎn)換成CPU指令,因而也就不需要加載Silverlight的程序集,從而避免了異常的發(fā)生。
?
拆箱
“拆箱的代價比裝箱低得多,拆箱其實就是獲取一個指針的過程,該指針指向包含在一個對象中的原始值類型(數(shù)據(jù)字段),拆箱不要求在內(nèi)存中復(fù)制任何字段”?
下面的代碼將struct類型p裝箱成object并賦值給o,隨后又將o拆箱成Point并賦值給p。通常我們所指的拆箱便是(Point)o這個表達(dá)式,其實這個表達(dá)式包含了拆箱和賦值兩個操作。
1 public struct Point 2 { 3 public int X; 4 public int Y; 5 } 6 7 class Program 8 { 9 static void Main(string[] args) 10 { 11 Point p = new Point() { X = 1, Y = 1 }; 12 object o = p; 13 p = (Point)o; 14 } 15 }單純地就拆箱來講只是獲取一個指針,但隨后會緊接著一個賦值的動作。那么這個值是賦到哪里呢?我們來嘗試著將拆箱后的o中的X的值直接改成2,編譯的時候我們會得到一個“Cannot modify the result of an unboxing conversion”,從MSDN可以得知,這是CS0445的編譯錯誤,從該錯誤的MSDN解釋可得知,我們是將拆箱的值賦值到內(nèi)存中的臨時變量中的。因此要記住,我們是不能直接修改拆箱結(jié)果的值的,必須先將其賦值程序中事先定義好的變量中。
1 ((Point)o).X = 2;由于個人能力所限,文中解釋不免有不足和錯誤之處,望各位讀者不吝指正,供大家共同學(xué)習(xí)進(jìn)步,也便于以后分享更好的文章。
Source
轉(zhuǎn)載于:https://www.cnblogs.com/chainyy/archive/2013/01/12/2857147.html
總結(jié)
以上是生活随笔為你收集整理的CLR via C# 之管中窥豹(一)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 关于索爱MT15i连接win7——MTP
- 下一篇: C# 事务提交(非数据库)