轉型和類型轉換 (C# 程式設計指南)
因為 C# 在編譯時間是靜態型別,所以在宣告變數之後,除非該型別隱含轉換為變數的型別,否則無法再次宣告或指派另一個型別的值。 例如,string
無法隱含轉換為 int
。 因此,在將 i
宣告為 int
之後,您便無法將字串 "Hello" 指派給它,如以下程式碼所示:
int i;
// error CS0029: can't implicitly convert type 'string' to 'int'
i = "Hello";
不過,您有時可能需要將值複製至另一種類型的變數或方法參數。 例如,您的整數變數可能需要傳遞給參數類型為 double
的方法。 或者,您可能需要將類別變數指派給介面類型的變數。 這些類型的作業稱為「類型轉換」。 在 C# 中,您可以執行下列類型的轉換:
隱含轉換:因為轉換一律會成功且不會遺失任何資料,所以不需要特殊的語法。 範例包括從較小到較大整數型別的轉換,以及從衍生類別到基底類別的轉換。
明確轉換 (強制型轉):明確轉換需要強制型轉運算式。 如果資訊可能會在轉換時遺失,或轉換因其他原因而失敗,則需要轉換。 一般範例包括將數字轉換為較少有效位數或較小範圍的類型,以及將基底類別執行個體轉換為衍生類別。
使用者定義的轉換:使用者定義的轉換會使用特殊方法,您可以定義特殊方法以啟用沒有基底類別/衍生類別關聯性之自訂類型間的明確和隱含轉換。 如需詳細資訊,請參閱使用者定義轉換運算子。
使用協助程式類別轉換:若要轉換不相容類型 (例如,整數和 System.DateTime 物件,或十六進位字串和位元組陣列),您可以使用 System.BitConverter 類別、System.Convert 類別,以及內建數字類型的
Parse
方法 (例如,Int32.Parse)。 如需詳細資訊,請參閱如何將位元組陣列轉換為整數、如何將字串轉換為數字,以及如何在十六進位字串和數值類型間轉換。
隱含轉換
針對內建數字類型,如果要儲存的值可以放入變數中,而不需進行截斷或四捨五入,則可以進行隱含轉換。 針對整數型別,這表示來源型別的範圍是目標型別範圍的適當子集。 例如,型別為 long 的變數 (64 位元整數) 可儲存任何 int (32 位元整數) 能儲存的值。 在下列範例中,編譯器會將位於右側的 num
值隱含轉換為 long
型別,再將它指派給 bigNum
。
// Implicit conversion. A long can
// hold any value an int can hold, and more!
int num = 2147483647;
long bigNum = num;
如需所有隱含數值轉換的完整清單,請參閱內建數值轉換一文的隱含數值轉換一節。
針對參考型別,一律會執行從某個類別到其任何一個直接或間接基底類別或介面的隱含轉換。 因為衍生類別一律會包含基底類別的所有成員,所以不需要特殊語法。
Derived d = new Derived();
// Always OK.
Base b = d;
明確轉換
不過,如果進行轉換,而有遺失資訊的風險,則編譯器需要您執行稱為「強制型轉」的明確轉換。 強制型轉 (cast) 是一種明確通知編譯器您打算進行轉換,而且您知道資料可能會遺失,或強制型轉可能會在執行階段失敗的方式。 若要執行強制型轉,請在要轉換的值或變數前面的括弧中指定要強制型轉為的類型。 下列程式會將 double 轉型為 int。沒有強制型轉,就不會編譯程式。
class Test
{
static void Main()
{
double x = 1234.7;
int a;
// Cast double to int.
a = (int)x;
System.Console.WriteLine(a);
}
}
// Output: 1234
如需受支援明確數值轉換的完整清單,請參閱內建數值轉換一文的明確數值轉換一節。
針對參考型別,如果您需要將基底類型轉換為衍生類型,則需要明確轉換︰
// Create a new derived type.
Giraffe g = new Giraffe();
// Implicit conversion to base type is safe.
Animal a = g;
// Explicit conversion is required to cast back
// to derived type. Note: This will compile but will
// throw an exception at run time if the right-side
// object is not in fact a Giraffe.
Giraffe g2 = (Giraffe)a;
參考型別之間的強制型轉作業不會變更基礎物件的執行階段類型;其只會變更將用作該物件之參考值的類型。 如需詳細資訊,請參閱多型。
執行階段的類型轉換例外狀況
在某些參考型別轉換中,編譯器無法判斷強制型轉是否有效。 正確編譯的強制型轉作業可能會在執行階段失敗。 如下列範例所示,在執行階段失敗的型別強制型轉將導致擲回 InvalidCastException。
class Animal
{
public void Eat() => System.Console.WriteLine("Eating.");
public override string ToString() => "I am an animal.";
}
class Reptile : Animal { }
class Mammal : Animal { }
class UnSafeCast
{
static void Main()
{
Test(new Mammal());
// Keep the console window open in debug mode.
System.Console.WriteLine("Press any key to exit.");
System.Console.ReadKey();
}
static void Test(Animal a)
{
// System.InvalidCastException at run time
// Unable to cast object of type 'Mammal' to type 'Reptile'
Reptile r = (Reptile)a;
}
}
Test
方法具有 Animal
參數,因此明確地將引數 a
強制型轉成 Reptile
會使其成為一個危險的假設動作。 不做假設性的動作,而是檢查類型較為安全。 C# 提供 is 運算子,可讓您先測試相容性,再實際執行轉換。 如需詳細資訊,請參閱如何使用模式比對以及 as 和 is 運算子進行安全轉換。