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風格強制型別轉換?

先來看一段程式碼:

  1. public class Base
  2. {
  3. public void Read()
  4. {
  5. Console.WriteLine("read");
  6. }
  7. }
  8.  
  9. public class Derived : Base
  10. {
  11. public void Write()
  12. {
  13. Console.WriteLine("Derived write");
  14. }
  15. }
  16.  
  17. public class CTest
  18. {
  19. public void check_c() // 採用舊式C風格的強制轉換
  20. {
  21. object der = new Derived();
  22. try
  23. {
  24. Base bas = (Base)der;
  25. if (null != bas)
  26. {
  27. bas.Read();
  28. }
  29. else
  30. {
  31. Console.WriteLine("C Cast failed!");
  32. }
  33. }
  34. catch (Exception error)
  35. {
  36. Console.WriteLine(error.ToString());
  37. }
  38. }
  39. public void check_as() // 採用as運算子強制轉換
  40. {
  41. object obj = new Derived();
  42. Base bas = obj as Base;
  43. if (null != bas)
  44. {
  45. bas.Read();
  46. }
  47. else
  48. {
  49. Console.WriteLine("As Cast failed!");
  50. }
  51.  
  52. }
  53. }

顯然,如果要你從check_c()和check_as()方法中選擇,你肯定會選後者。因為兩者相比較後者具有:

1、 減少了效能開銷(try/catch結構的效能開銷)
2、 精簡了程式碼
3、 更安全,as轉換不會有異常丟擲,如果轉換失敗,也會安全的返回null。

什麼情況下使用C風格強制轉換

1、使用者定義型別轉換(http://msdn.microsoft.com/zh-cn/vstudio/ms173105.aspx)。

  1. public class Wheel
  2. {
  3. public void Say()
  4. {
  5. Console.WriteLine(" I'm a wheel.");
  6. }
  7. }
  8. public class Car
  9. {
  10. private Wheel _wheel = new Wheel();
  11. public void Say()
  12. {
  13. Console.WriteLine("I'm a cal with only one wheel.");
  14. }
  15. public static implicit operator Wheel(Car itemCar)
  16. {
  17. return itemCar._wheel;
  18. }
  19. }

注:implicit 關鍵字用於宣告隱式的使用者定義型別轉換運算子

  1. class Program
  2. {
  3. static void Main(string[] args)
  4. {
  5. object itemCar = new Car();
  6. Cast(itemCar);
  7. Console.ReadLine();
  8. }
  9. private static void Cast(object obj)
  10. {
  11. Car itemCar = obj as Car;
  12. if (null != itemCar)
  13. {
  14. try
  15. {
  16. Wheel itemWheel = (Wheel)itemCar;
  17. if (null != itemWheel)
  18. {
  19. itemWheel.Say();
  20. }
  21. }
  22. catch (Exception error)
  23. {
  24.  
  25. }
  26. }
  27. }
  28. }

在上面的main函式中如果將 Cast(itemCar)改成Wheel itemWheel = itemCar as Wheel將會發生第一種錯誤:編譯可

以通過,但是轉換會失敗。另外如果你將main函式改成如下形式,將會發生第二種錯誤:編譯無法通過。

  1. static void Main(string[] args)
  2. {
  3. Car itemCar = new Car();
  4. Wheel itemWheel = itemCar as Wheel;
  5. itemWheel.Say();
  6. Console.ReadLine();
  7. }

第一種錯誤發生的原因是:itemCar被定義為object型別,在編譯時將itemCar以System.Object型別生成IL程式碼,執行

時法無法將object型別轉換成Wheel型別。第二種錯誤發生的原因是:Car型別和Wheel型別不相容,既不符合引用轉換的要求
,更不符合裝箱轉換的要求。在Cast(object obj)函式中如果去掉
Car itemCar = obj as Car 同理也會發生第一種錯誤。

2、 值資料型別的轉換,同時採用is運算子來取消可能因轉換引發的異常。

  1. object obj = Value();
  2. int i = ;
  3. if ( obj is int )
  4. 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判斷是無意義的。

  1. object obj = Value();
  2. if (itemCar is Car)
  3. {
  4. Car itemCar = obj as Car;
  5. }

2、在用C風格進行強制型別轉換前儘量要採用is運算子進行型別判斷。

  1. object obj = Value();
  2. if (itemCar is Car)
  3. {
  4. Car itemCar = (Car)obj;
  5. }

總之,在能用as運算子的情況下絕不使用C風格的強制轉換。因為as運算子比起C風格盲目的強制轉換,as運算子更安

全,而且在執行時效率更高。