http://www.cnblogs.com/JiangSoney/archive/2009/08/07/1541488.html
MSDN: https://msdn.microsoft.com/zh-cn/vstudio/cc488006
C#是一種強資料型別語言。(一種總是強制型別定義的語言。如果你有一個整數,如果不顯示地進行轉換,你不能將其視為
一個字串。)好的程式設計習慣提醒我們要儘量避免使用強制轉換,但是有的時候我們是無法避免的。
強制轉換適用情況:源變數和目標變數相容。即使這樣也存在資料丟失的風險,因為目標變數的型別大小比源變數小或者目
標變數是源變數的一個基類。
在c#裡,你有兩種方法來實現強制轉化:
A、採用as運算子;
B、舊式的C風格“(type)object”。
那麼我們應該什麼時候採用as運算子,什麼時候採用舊式C風格強制型別轉換?
先來看一段程式碼:
- public class Base
- {
- public void Read()
- {
- Console.WriteLine("read");
- }
- }
- public class Derived : Base
- {
- public void Write()
- {
- Console.WriteLine("Derived write");
- }
- }
- public class CTest
- {
- public void check_c() // 採用舊式C風格的強制轉換
- {
- object der = new Derived();
- try
- {
- Base bas = (Base)der;
- if (null != bas)
- {
- bas.Read();
- }
- else
- {
- Console.WriteLine("C Cast failed!");
- }
- }
- catch (Exception error)
- {
- Console.WriteLine(error.ToString());
- }
- }
- public void check_as() // 採用as運算子強制轉換
- {
- object obj = new Derived();
- Base bas = obj as Base;
- if (null != bas)
- {
- bas.Read();
- }
- else
- {
- Console.WriteLine("As Cast failed!");
- }
- }
- }
顯然,如果要你從check_c()和check_as()方法中選擇,你肯定會選後者。因為兩者相比較後者具有:
1、 減少了效能開銷(try/catch結構的效能開銷)
2、 精簡了程式碼
3、 更安全,as轉換不會有異常丟擲,如果轉換失敗,也會安全的返回null。
什麼情況下使用C風格強制轉換
1、使用者定義型別轉換(http://msdn.microsoft.com/zh-cn/vstudio/ms173105.aspx)。
- public class Wheel
- {
- public void Say()
- {
- Console.WriteLine(" I'm a wheel.");
- }
- }
- public class Car
- {
- private Wheel _wheel = new Wheel();
- public void Say()
- {
- Console.WriteLine("I'm a cal with only one wheel.");
- }
- public static implicit operator Wheel(Car itemCar)
- {
- return itemCar._wheel;
- }
- }
注:implicit 關鍵字用於宣告隱式的使用者定義型別轉換運算子
- class Program
- {
- static void Main(string[] args)
- {
- object itemCar = new Car();
- Cast(itemCar);
- Console.ReadLine();
- }
- private static void Cast(object obj)
- {
- Car itemCar = obj as Car;
- if (null != itemCar)
- {
- try
- {
- Wheel itemWheel = (Wheel)itemCar;
- if (null != itemWheel)
- {
- itemWheel.Say();
- }
- }
- catch (Exception error)
- {
- }
- }
- }
- }
在上面的main函式中如果將 Cast(itemCar)改成Wheel itemWheel = itemCar as Wheel將會發生第一種錯誤:編譯可
以通過,但是轉換會失敗。另外如果你將main函式改成如下形式,將會發生第二種錯誤:編譯無法通過。
- static void Main(string[] args)
- {
- Car itemCar = new Car();
- Wheel itemWheel = itemCar as Wheel;
- itemWheel.Say();
- Console.ReadLine();
- }
第一種錯誤發生的原因是:itemCar被定義為object型別,在編譯時將itemCar以System.Object型別生成IL程式碼,執行
時法無法將object型別轉換成Wheel型別。第二種錯誤發生的原因是:Car型別和Wheel型別不相容,既不符合引用轉換的要求
,更不符合裝箱轉換的要求。在Cast(object obj)函式中如果去掉
Car itemCar = obj as Car 同理也會發生第一種錯誤。
2、 值資料型別的轉換,同時採用is運算子來取消可能因轉換引發的異常。
- object obj = Value();
- int i = ;
- if ( obj is int )
- i = ( int ) obj;
什麼情況下使用as運演算法轉換
1、 引用轉換
A、 隱式引用轉換(http://msdn.microsoft.com/zh-cn/library/aa691284(VS.71).aspx);
B、 顯示引用轉換(http://msdn.microsoft.com/zh-cn/library/aa691291(VS.71).aspx)。
2、 裝箱轉換(http://msdn.microsoft.com/zh-cn/library/aa691158(VS.71).aspx)。
上面提到在用C風格進行強制型別轉換前要採用is運算子進行型別判斷,那麼is運算子究竟是有什麼功能,is運算子和
as運算子有什麼區別,我們在使用is運算子時應該注意哪些問題。
is運算子是型別判斷運算子,檢查物件是否與給定型別相容,和as運算子一樣是安全的,不會發生異常的,與as運算
符不同的是:is運算子不進行型別轉換,只返回bool值,表示型別是否相容。在使用is運算子時注意一下幾點:
1、避免冗餘。如下面的程式碼就出現了冗餘,實際上is判斷是無意義的。
- object obj = Value();
- if (itemCar is Car)
- {
- Car itemCar = obj as Car;
- }
2、在用C風格進行強制型別轉換前儘量要採用is運算子進行型別判斷。
- object obj = Value();
- if (itemCar is Car)
- {
- Car itemCar = (Car)obj;
- }
總之,在能用as運算子的情況下絕不使用C風格的強制轉換。因為as運算子比起C風格盲目的強制轉換,as運算子更安
全,而且在執行時效率更高。