- C# 2012程序設計實踐教程 (清華電腦學堂)
- 張冬旭
- 1962字
- 2021-03-26 17:16:26
2.4 類型轉換
在數據類型中曾介紹,"5"、'5'和5是3個不同的數據類型,其中,只有5能參與數據的數學運算。編譯器編譯程序運行時需要確切地知道數據類型,所以在實際開發中,若需要將"5"和'5'作為整型數據參與運算,則需要將"5"和'5'先改變數據類型,使其變成5,再進行運算。
本節介紹各個數據類型之間的轉換,包括基本數據類型間的顯式轉換和隱式轉換、字符串和基本數值類型之間的轉換,以及對象類型的轉換。
2.4.1 隱式轉換和顯式轉換
由于不同的數據類型有著不同的長度和精度,因此長度和精度較大的數據類型在轉換為長度和精度較小的數據類型時,可能存在數據的丟失。如浮點數3.14轉換為整型之后是3,其小數點后面的內容將丟失。這種轉換是強制性的,是需要顯式轉換的。
相反,長度和精度較小的數據類型在轉換為長度和精度較大的數據類型時,沒有數據的丟失,是可以直接轉換的,如3轉換為浮點數為3.0,數據值與原數據是一樣的。在使用時可直接將3作為3.0參與程序中,這種轉換稱為隱式轉換。
1.隱式轉換
隱式轉換必須是將范圍小的類型轉換為范圍大的類型。如將int類型轉換為double、long、decimal或float類型,將long類型轉換為float或double類型等。如表2-4所示為隱式類型的轉換表。
表2-4 隱式類型轉換

在表2-4中,從int、uint、long、ulong到float,以及從long或ulong到double的轉換可能會導致精度損失,但是不會影響它的數量級,而且隱式轉換不會丟失任何信息。
2.顯式轉換
顯式類型轉換也被稱作強制類型轉換,它需要在代碼中明確地聲明要轉換的類型。顯式類型轉換可以將取值范圍大的類型轉換為取值范圍小的類型。如表2-5所示列出了需要進行顯式類型轉換的數據類型。
表2-5 顯式類型轉換

C#中使用強制類型進行轉換時有兩種方法:一種是使用括號(),在括號()中給出數據類型標識符(即強制轉換的類型),在括號外要緊跟轉換的表達式;另外一種是使用Convert關鍵字進行數據類型的強制轉換。
2.4.2 字符串類型轉換
顯式類型轉換和隱式類型轉換主要是對數值之間的轉換,本節介紹字符串與數值之間的轉換。
字符串類型轉換為其他類型時有兩種方法:一種是使用parse()方法;另外一種是使用Convert類中的方法進行轉換。如表2-6所示列出了Convert類的常用轉換方法。
表2-6 Convert類的常用轉換方法

字符串轉換中,最常用的是字符串和數學數據之間的轉換。如將字符串轉換為能夠執行數學運算的數據,參與到數學運算中,如范例3所示。
【范例3】
加號(+)有將數值相加的作用,也有連接字符串的作用。定義字符串類型的兩個值“12”和“34”,輸出兩個變量執行“+”之后的值;將兩個變量轉換為整型執行“+”運算,輸出結果,代碼如下。
string num1 = "12"; string num2 = "34"; string strnum = num1 + num2; int intnum = Convert.ToInt32(num1) + Convert.ToInt32(num2); Console.WriteLine("兩個字符串的和:{0}", strnum); Console.WriteLine("兩個整型數的和:{0}", intnum);
上述代碼的執行結果如下所示。
兩個字符串的和:1234 兩個整型數的和:46
由上述結果可以看出,作為字符串類型時,兩個變量的相加結果,相當于將兩個字符串中的字符組合在一起,而轉換為整型后,其相加結果為數學運算中的相加值。
注意
將字符串轉換為其他類型時該字符串必須是數字的有效表示形式。例如,用戶可以把字符串“32”轉換為int類型,卻不能將字符串“name”轉換為整數,因為它不是整數有效的形式。
2.4.3 裝箱和拆箱
裝箱是值類型到Object類型或到此值類型所實現的任何接口類型的隱式轉換,用于在垃圾回收堆中存儲值類型。
裝箱實際上是指將值類型轉換為引用類型的過程,裝箱的執行過程大致可以分為以下三個階段。
(1)從托管堆中為新生成的引用對象分配內存。
(2)將值類型的實例字段復制到新分配的內存中。
(3)返回托管堆中新分配對象的地址,該地址就是一個指向對象的引用了。
如下代碼演示了如何將int類型的變量val進行裝箱操作,然后將裝箱后的值進行輸出。
int val = 100; object obj = val; //裝箱 Console.WriteLine ("對象的值 = {0}", obj); //輸出結果
裝箱操作生成的是全新的引用對象,這會損耗一部分的時間,因此會造成效率的降低,所以應該盡量避免裝箱操作。一般情況下,符合下面的情況時可以執行裝箱操作。
(1)調用一個含Object類型的參數方法時,該Object可以支持任意的類型以方便通用,當開發人員需要將一個值類型(如Int32)傳入時就需要裝箱。
(2)使用一個非泛型的容器,其目的是為了保證能夠通用。因此可以將元素類型定義為Object,于是如果要將值類型數據加入容器時需要裝箱。
拆箱也叫取消裝箱,它是與裝箱相反的操作,它是從Object類型到值類型或從接口類型到實現該接口的值類型的顯式轉換。
拆箱實際上是指從引用類型到值類型的過程,拆箱的執行過程大致可以分為以下兩個階段。
(1)檢查對象實例,確保它是給定值類型的一個裝箱值。
(2)將該值從實例復制到值類型變量中。
如下示例代碼演示了基本的拆箱操作。
int val = 100; object obj = val; //裝箱 int num = (int) obj; //拆箱 Console.WriteLine ("num:{0}", num); //輸出結果
注意
當一個裝箱操作把值類型轉換成一個引用類型時,不需要顯式地強制類型轉換;而拆箱操作把引用類型轉換到值類型時,由于它可以強制轉換到任何可以相容的值類型,所以必須顯式地強制類型轉換。