whitefox 發表於 2023-11-16 16:26:17

[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)public static implicit operator Destination(Source src)
{
    return new Destination();
}2. 明確轉換/顯示轉換(explicit)public static explicit operator Destination(Source src)
{
    return new Destination();
}這裡用一個例子實際演練,這三個類別的數字越大模擬表示精度越高的情況
精度低轉高用 implicit,精度高轉低用 explicit
先宣告三個自訂類別,這三個類別結構各自有一個字串屬性跟兩個型別轉換的方法public class Lv1
{
    private string _Name;
    public string Name
    {
        get { return _Name; }
        set
        {
            _Name = value;
        }
    }

    public Lv1(string LvName)
    {
        this.Name = LvName;
    }

    public static implicit operator Lv2(Lv1 lv1)
    {
        return new Lv2("(隱式轉換至Lv2)" + lv1.Name);
    }
    public static implicit operator Lv3(Lv1 lv1)
    {
        return new Lv3("(隱式轉換至Lv3)" + lv1.Name);
    }
}
public class Lv2
{
    private string _Name;
    public string Name
    {
        get { return _Name; }
        set
        {
            _Name = value;
        }
    }

    public Lv2(string LvName)
    {
        this.Name = LvName;
    }

    public static explicit operator Lv1(Lv2 lv2)
    {
        return new Lv1("(顯式轉換至Lv1)" + lv2.Name);
    }
    public static implicit operator Lv3(Lv2 lv2)
    {
        return new Lv3("(隱式轉換至Lv3)" + lv2.Name);
    }
}
public class Lv3
{
    private string _Name;
    public string Name
    {
        get { return _Name; }
        set
        {
            _Name = value;
        }
    }

    public Lv3(string LvName)
    {
        this.Name = LvName;
    }

    public static explicit operator Lv1(Lv3 lv3)
    {
        return new Lv1("(顯式轉換至Lv1)" + lv3.Name);
    }
    public static explicit operator Lv2(Lv3 lv3)
    {
        return new Lv2("(顯式轉換至Lv2)" + lv3.Name);
    }
}txtObj1/txtObj2/txtObj3 是 TextBox 輸入控制元件用來給類別的 Name 屬性賦值
txtContent 是 TextBlock 顯示文字控制元件用來顯示資訊Lv1 L1 = new Lv1(txtObj1.Text);
Lv2 L2 = new Lv2(txtObj2.Text);
Lv3 L3 = new Lv3(txtObj3.Text);

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

Lv1 tmpL1;
Lv2 tmpL2;
Lv3 tmpL3;

txtContent.Text = txtContent.Text + "\r\n";
tmpL2 = L1;
txtContent.Text = txtContent.Text +
                          txtObj1.Text + " 轉 " + txtObj2.Text +
                          "→" + tmpL2.Name + "\r\n";
tmpL3 = L1;
txtContent.Text = txtContent.Text +
                          txtObj1.Text + " 轉 " + txtObj3.Text +
                          "→" + tmpL3.Name + "\r\n";

txtContent.Text = txtContent.Text + "\r\n";
tmpL1 = (Lv1)L2;
txtContent.Text = txtContent.Text +
                          txtObj2.Text + " 轉 " + txtObj1.Text +
                          "→" + tmpL1.Name + "\r\n";
tmpL3 = L2;
txtContent.Text = txtContent.Text +
                          txtObj2.Text + " 轉 " + txtObj3.Text +
                          "→" + tmpL3.Name + "\r\n";

txtContent.Text = txtContent.Text + "\r\n";
tmpL1 = (Lv1)L3;
txtContent.Text = txtContent.Text +
                          txtObj3.Text + " 轉 " + txtObj1.Text +
                          "→" + tmpL1.Name + "\r\n";
tmpL2 = (Lv2)L3;
txtContent.Text = txtContent.Text +
                          txtObj3.Text + " 轉 " + txtObj2.Text +
                          "→" + tmpL2.Name + "\r\n";執行結果:

whitefox 發表於 2023-11-16 16:43:21

再補充一下
當兩個類別互相轉換的方法可以寫在來源類別(Source)內或目標類別(Destination)內
但不能同時存在兩個類別內!
可以嘗試把上面例子 Lv1 內的 public static implicit operator Lv2(Lv1 lv1) 方法剪貼到 Lv2 內依然正確執行
但實務上建議把轉換方法寫在來源類別內維護起來也比較直覺
頁: [1]
查看完整版本: [C#] 型別轉換關鍵字 implicit/explicit