冰楓論壇

標題: [C#] 型別轉換關鍵字 implicit/explicit [打印本頁]

作者: whitefox    時間: 2023-11-16 16:26
標題: [C#] 型別轉換關鍵字 implicit/explicit
C#中當宣告一個變數類型之後,需要將此變數指派給另一個類型的值就要用到類型轉換
這裡的類型轉換有兩種
1. 隱含轉換/隱式轉換(implicit)
- 使用上不需要特殊語法便可以轉型
- 應用場景是型別轉換不會造成資料失真(或精度損失);比如從整數 int 轉為浮點數 float
2. 明確轉換/顯示轉換(explicit)
- 使用上需要用強制型轉運算式: (T)E → 表示從型別 E 轉成型別 T
- 應用場景是型別轉換會有資料誤差或會因此造成錯誤產生,需額外做處理的情況

型別轉換方法的宣告須具備以下因素
1. 存取修飾詞須是 public
2. 宣告為靜態方法 static
3. 使用關鍵字 implicit 或 explicit
4. 使用運算子宣告關鍵字 operator
5. 定義轉換的型別(以下寫為 Destination)
6. 傳入欲轉換的型別(以下寫為 Source)

具體宣告定義型別轉換方法的語句格式如下
1. 隱含轉換/隱式轉換(implicit)
  1. public static implicit operator Destination(Source src)
  2. {
  3.     return new Destination();
  4. }
複製代碼
2. 明確轉換/顯示轉換(explicit)
  1. public static explicit operator Destination(Source src)
  2. {
  3.     return new Destination();
  4. }
複製代碼
這裡用一個例子實際演練,這三個類別的數字越大模擬表示精度越高的情況
精度低轉高用 implicit,精度高轉低用 explicit
先宣告三個自訂類別,這三個類別結構各自有一個字串屬性跟兩個型別轉換的方法
  1. public class Lv1
  2. {
  3.     private string _Name;
  4.     public string Name
  5.     {
  6.         get { return _Name; }
  7.         set
  8.         {
  9.             _Name = value;
  10.         }
  11.     }

  12.     public Lv1(string LvName)
  13.     {
  14.         this.Name = LvName;
  15.     }

  16.     public static implicit operator Lv2(Lv1 lv1)
  17.     {
  18.         return new Lv2("(隱式轉換至Lv2)" + lv1.Name);
  19.     }
  20.     public static implicit operator Lv3(Lv1 lv1)
  21.     {
  22.         return new Lv3("(隱式轉換至Lv3)" + lv1.Name);
  23.     }
  24. }
  25. public class Lv2
  26. {
  27.     private string _Name;
  28.     public string Name
  29.     {
  30.         get { return _Name; }
  31.         set
  32.         {
  33.             _Name = value;
  34.         }
  35.     }

  36.     public Lv2(string LvName)
  37.     {
  38.         this.Name = LvName;
  39.     }

  40.     public static explicit operator Lv1(Lv2 lv2)
  41.     {
  42.         return new Lv1("(顯式轉換至Lv1)" + lv2.Name);
  43.     }
  44.     public static implicit operator Lv3(Lv2 lv2)
  45.     {
  46.         return new Lv3("(隱式轉換至Lv3)" + lv2.Name);
  47.     }
  48. }
  49. public class Lv3
  50. {
  51.     private string _Name;
  52.     public string Name
  53.     {
  54.         get { return _Name; }
  55.         set
  56.         {
  57.             _Name = value;
  58.         }
  59.     }

  60.     public Lv3(string LvName)
  61.     {
  62.         this.Name = LvName;
  63.     }

  64.     public static explicit operator Lv1(Lv3 lv3)
  65.     {
  66.         return new Lv1("(顯式轉換至Lv1)" + lv3.Name);
  67.     }
  68.     public static explicit operator Lv2(Lv3 lv3)
  69.     {
  70.         return new Lv2("(顯式轉換至Lv2)" + lv3.Name);
  71.     }
  72. }
複製代碼
txtObj1/txtObj2/txtObj3 是 TextBox 輸入控制元件用來給類別的 Name 屬性賦值
txtContent 是 TextBlock 顯示文字控制元件用來顯示資訊
  1. Lv1 L1 = new Lv1(txtObj1.Text);
  2. Lv2 L2 = new Lv2(txtObj2.Text);
  3. Lv3 L3 = new Lv3(txtObj3.Text);

  4. txtContent.Text = "初始狀態:\r\n" +
  5.                           "第一層:" + L1.Name + "\r\n" +
  6.                           "第二層:" + L2.Name + "\r\n" +
  7.                           "第三層:" + L3.Name + "\r\n" ;

  8. Lv1 tmpL1;
  9. Lv2 tmpL2;
  10. Lv3 tmpL3;

  11. txtContent.Text = txtContent.Text + "\r\n";
  12. tmpL2 = L1;
  13. txtContent.Text = txtContent.Text +
  14.                           txtObj1.Text + " 轉 " + txtObj2.Text +
  15.                           "→" + tmpL2.Name + "\r\n";
  16. tmpL3 = L1;
  17. txtContent.Text = txtContent.Text +
  18.                           txtObj1.Text + " 轉 " + txtObj3.Text +
  19.                           "→" + tmpL3.Name + "\r\n";

  20. txtContent.Text = txtContent.Text + "\r\n";
  21. tmpL1 = (Lv1)L2;
  22. txtContent.Text = txtContent.Text +
  23.                           txtObj2.Text + " 轉 " + txtObj1.Text +
  24.                           "→" + tmpL1.Name + "\r\n";
  25. tmpL3 = L2;
  26. txtContent.Text = txtContent.Text +
  27.                           txtObj2.Text + " 轉 " + txtObj3.Text +
  28.                           "→" + tmpL3.Name + "\r\n";

  29. txtContent.Text = txtContent.Text + "\r\n";
  30. tmpL1 = (Lv1)L3;
  31. txtContent.Text = txtContent.Text +
  32.                           txtObj3.Text + " 轉 " + txtObj1.Text +
  33.                           "→" + tmpL1.Name + "\r\n";
  34. tmpL2 = (Lv2)L3;
  35. txtContent.Text = txtContent.Text +
  36.                           txtObj3.Text + " 轉 " + txtObj2.Text +
  37.                           "→" + tmpL2.Name + "\r\n";
複製代碼
執行結果:
Result.png
作者: whitefox    時間: 2023-11-16 16:43
再補充一下
當兩個類別互相轉換的方法可以寫在來源類別(Source)內或目標類別(Destination)內
但不能同時存在兩個類別內!
可以嘗試把上面例子 Lv1 內的 public static implicit operator Lv2(Lv1 lv1) 方法剪貼到 Lv2 內依然正確執行
但實務上建議把轉換方法寫在來源類別內維護起來也比較直覺




歡迎光臨 冰楓論壇 (https://bingfong.com/) Powered by 冰楓