在.Net下面,我們做類型的強制轉換有兩種方式,比如把對象o轉換成A類型的對象:
1。 A a = (A)o;
2。 A a = o as A;
那麼這兩種方式有什麼區別呢?或者說有區分它們的必要麼?看了我下面的分析,大家自然就明白了。
實際上,對這個問題不能一概而論,需要考慮這樣幾種情況。
第一種情況:o是A的子類。
在這種情況下,無論是用方法1還是方法2,效果都是一樣的!通過查看上面兩種方法的IL代碼,會發現它們的IL代碼是完全一樣的,都是簡單的把o出棧,然後保存到a的位置。
因此,當o是A的子類的時候,兩種方式沒有區別。
現在考慮第二種情況:o不是A的子類。
舉個例子,假如o就是object類型吧。
查看兩者的IL代碼,會發現在第1種方法裡面,在把o出棧之後,做了一個castclass操作,它嘗試把o轉換成A類型。如果成功,當然沒的說了。如果失敗了,它會丟出一個Invalid cast異常。
在第2種方法裡面,在把o出棧之後,做了一個isinst操作,它檢測是否可以把o轉換成A類型。如果失敗了,後面的入棧操作會壓入一個null進去,也就是說,你的a變成了null。
好了,現在已經很明了了。可是,區分它們有什麼意義呢?
首先,在第一種情況下,我們當然不需要去區分它們了,隨便你怎麼都可以。因為它們根本就沒有區別!
但是在第二種情況下就有區別了。如果用第1種方法,就要考慮處理異常;如果用第2種方法,就必須得在使用a之前做一下非空檢測,否則很有可能出現“沒有實例化”的異常。但是,實際上,用第1種方法,也要進行非空檢測。這是為什麼呢?因為假如o是null的話,也是可以成功進行類型轉換的。這樣看來,無論用那種方法,進行非空檢測都是不能省的(當然如果你願意省掉我也沒說的),不過第1種方法還要多個異常處理才算完善。如此看來,使用第1種方法多少費點勁哦。
那麼,現在結論出來了——如果可以的話,盡量用as吧!再結合is關鍵字,在最後給出一個完善的類型轉換方案:
A a = o as A;
if (a is A)
...