【C#】你是誰 ? 型別轉換:測試運算子 is, as、Cast 運算式、typeof

  • 45
  • 0
  • C#
  • 2024-05-17

有時候傳進來的參數會是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,如果只是需要判斷類別,可以使用typeoftypeof 運算子會取得型別的 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