有時候傳進來的參數會是object,這個時候必須要知道他的型別才能做後續操作。還好C# 提供了很多型別轉換的測試運算,可以輕鬆做到這件事情。本文比較各種型別轉換的用法。
is, as
is 基本用法為 E is T
,其中E 可以是變數或是有回傳的運算式,T 是型別。E需要有值能轉換成非null時,則會回傳true
。可以寫成 E is T variable
,判斷之餘順便宣告一個變數來使用。
// 無法做隱含轉換
int number = 10;
object iBoxed = number;
Console.WriteLine(iBoxed is int); // True
Console.WriteLine(iBoxed is long); // False
// 雖然平常程式是可以寫 long number2 = number
// 但使用is 時無法做隱含轉換,所以會回傳false。
if(iBoxed is int castNumber)
{
// 成功轉換的castNumber 可以拿來操作
}
另外如果原本是子類別,可以轉換判斷成父類別;但反之則無法。甚至E 為空,則is 會回傳false
// 假設已經定義一個Class: Calendar
Calendar source = null;
object obj = source;
Console.WriteLine(obj is Calendar); // False
as 使用方法基本上跟is 差不多,但as 不會回傳true/false,且此時T 需要是 可null 型態,因為as 背後原理為 E is T ? (T)(E) : (T)null
,也就是最後回傳的是一個變數,故無法寫成 if(obj as Calendar)
。
以下為在程式碼中正確、安全的使用is、as 的範例
// 假設已經定義兩個Class: Calendar, CaseData
// using 'is'
Calendar source = null;
object obj = source;
if ( obj is CaseData data)
data.GetMessage();
else
{
// data 的生命週期只存在於上面的if,else 這邊無法使用
Console.WriteLine($"obj Type-Error");
}
// using 'as'
var data2 = obj as CaseData;
if (data2 != null) // 需要另外做null 判斷
Console.WriteLine(data2.GetMessage());
else
Console.WriteLine($"data2 Type-Error");
Cast
(T)E 會執行明確轉換,若明確轉換不存在,就會發生錯誤。
int number = 55;
Calendar test = (Calendar)number; // compile-error
object obj = number;
Calendar test2 = (Calendar)obj ; // runtime-error
typeof
以上說的幾種方式都是將E 轉成T,如果只是需要判斷類別,可以使用typeof
。typeof
運算子會取得型別的 System.Type 執行個體,搭配GetType() 一起使用。通常可以用在Reflection 的時候。
Console.WriteLine(typeof(List<string>));
// output: System.Collections.Generic.List`1[System.String]
var source = new Calendar();
object obj = source;
System.Type typeName = obj.GetType();
Console.WriteLine($"Type Name is '{typeName.Name}'");
// output: Type Name is 'Calendar'
Console.WriteLine(typeof(Calendar));
// output: 'Calendar'
// 用System.Type 比較
if(obj.GetType() == typeof(Calendar))
{
// do something...
}
References
型別測試運算子和轉換運算式會測試物件的執行階段型別 - C# | Microsoft Learn
如何使用模式比對和 is 及 as 運算子來進行安全轉換 - C# | Microsoft Learn