iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 19
1
Software Development

我要轉職成 C# / .NET 工程師系列 第 19

轉型(下)-實作轉型運算子、關於繼承關係轉型

  • 分享至 

  • xImage
  •  

實作轉型運算子

假設我們定義了兩個類別,分別是攝氏溫度類別華氏溫度類別,雖然我們可以在溫度類別中建立一個方法來轉型

攝氏 c = new 攝氏("37.5");
華氏 f = c.轉型成華氏();

但若我們希望能像如下進行型別轉換,我們可以實作轉型運算子。

攝氏 c = new 攝氏("37.5");
華氏 f = (華氏) c;

這兩個類別都是各自獨立的,我把溫度封裝在裡面,修改溫度的方式只有初始化類別時與使用調整溫度方法這兩個方式,並只有使用讀取溫度方法才能拿到類別中的溫度。
基礎架構如以下:

class 攝氏
{
        private double 溫度;
        public 攝氏(double 初始溫度){           
        }
        public void 調整溫度(double 設定值){         
        }
        public string 讀取溫度(){            
        }
}

實際上,初始化使可能會傳入double或字串,所以我的建構式可能有兩種,還要實作攝氏與華氏兩個類別的程式碼,實作結果如下:

class 攝氏
{
        private double 溫度;

        public 攝氏(double 初始溫度)
        {
            溫度 = 初始溫度;
        }
        public 攝氏(string 初始溫度)
        {
            溫度 = double.Parse(初始溫度);
        }

        public void 調整溫度(double 設定值)
        {
            溫度 = 設定值;
        }
        public string 讀取溫度()
        {
            string 溫度C = 溫度.ToString() + "ºC";
            return 溫度C;
        }
}

class 華氏
{
        private double 溫度;
        public 華氏(double 初始溫度)
        {
            溫度 = 初始溫度;
        }
        public 華氏(string 初始溫度)
        {
            溫度 = double.Parse(初始溫度);
        }

        public void 調整溫度(double 設定值)
        {
            溫度 = 設定值;
        }
        public string 讀取溫度()
        {
            string 溫度F = 溫度.ToString() + "ºF";
            return 溫度F;
        }        
 }

現在就可以開始用operator關鍵字製作自己的轉型運算子,這邊我要做明確轉型的運算子,那就要用explicit關鍵字,另外規定轉型運算子要設定成static,讓程式執行前準備好運算子,免得要轉型時還沒建立物件,另外,特別的地方在於運算子可以寫在兩個物件任一方,C#會在欲轉型與被轉型兩方尋找轉換運算子

class 華氏
    {
        ...省略先前內容...
        
        public static explicit operator 華氏(攝氏 c)
        {
            string 攝氏溫度 = c.讀取溫度();
            string[] 分割 = 攝氏溫度.Split('º');
            double 溫度轉換 = double.Parse(分割[0]) / 5 * 9 + 32;
            華氏 f = new 華氏(溫度轉換);
            return f;
        }
    }
class 攝氏
    {
        ...省略先前內容...
        
        public static explicit operator 攝氏(華氏 f)
        {
            string 華氏溫度 = f.讀取溫度();
            string[] 分割 = 華氏溫度.Split('º');
            double 溫度轉換 = (double.Parse(分割[0]) - 32) / 9 * 5;
            攝氏 c = new 攝氏(溫度轉換);
            return c;
        }
    }

我們可以寫個小程式觀看實作結果

static void Main(string[] args)
{
    攝氏 c = new 攝氏(37.5);
    Console.WriteLine(c.讀取溫度());

    華氏 f = (華氏)c;
    Console.WriteLine(f.讀取溫度());
    c = (攝氏)f;
    Console.WriteLine(c.讀取溫度());

    Console.ReadKey();
}

https://ithelp.ithome.com.tw/upload/images/20191005/20120420UEfpF16SbW.png

類別庫提供的轉型方法

我們可以使用System命名空間,提供的Convert類別裡面的轉型方法進行轉型。例如以下:

int i = System.Convert.ToInt32("12345");

可以從https://referencesource.microsoft.com
看到Convert實作的原始碼,有些方法也是直接使用轉型運算子。
https://ithelp.ithome.com.tw/upload/images/20191005/201204202P7nmdT9Cf.png

繼承轉型

繼承轉型是CLR在背後幫我們依繼承關係自動轉型,而非轉型計算子,例如:

int i = 123;
object o = i; //CLR幫我們自動轉型成object;
int j = (int) o //需明確告知CLR欲轉成哪個object子型別,此轉換是依靠CLR而非轉型運算子

又例如以下,B繼承於A:

class A
    {
        public int numberA;
        
    }
class B : A
    {
        public int numberB;
    }

當物件B,在宣告為A或object,CLR會幫我們自動轉型。


object o1 = new B();
A o2 = new B();

若要把宣告為A的物件o2轉回為B,則需明確告知CLR

B o3 = (B) o2;

繼承關係轉型隨時都在發生

以下為例,字串+整數時,整數會被轉換成object
https://ithelp.ithome.com.tw/upload/images/20191005/20120420OaNt4GuuYu.png


上一篇
轉型(上篇)、boxing、unboxing
下一篇
可為null的型別
系列文
我要轉職成 C# / .NET 工程師34
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言