分享方式:


型別測試運算子及 Cast 運算式 - isastypeof 和轉換

這些運算子和運算式會執行型別檢查或型別轉換。 is 運算子會檢查運算式的執行階段型別是否與給定型別相容。 as 運算子會將運算式明確地轉換成給定的型別 (如果其執行階段型別與該型別相容)。 轉換運算式會執行對目標型別的明確轉換。 typeof 運算子會取得某個型別的 System.Type 執行個體。

is 運算子

is 運算子會檢查運算式結果的執行階段型別是否與給定型別相容。 is 運算子也會對將運算式結果對模式進行測試。

使用型別測試 is 運算子運算式有下列格式

E is T

其中 E 是會傳回值的運算式,而 T 是型別名稱或型別參數。 E 不能是匿名方法或 Lambda 運算式。

當運算式結果為非 Null 且下列任何條件成立時,is 運算子會傳回 true

is 運算子不會考慮使用者定義轉換。

下列範例示範當運算式結果的執行階段型別衍生自給定型別 (表示型別之間存在參考轉換) 時,is 運算子傳回 true

public class Base { }

public class Derived : Base { }

public static class IsOperatorExample
{
    public static void Main()
    {
        object b = new Base();
        Console.WriteLine(b is Base);  // output: True
        Console.WriteLine(b is Derived);  // output: False

        object d = new Derived();
        Console.WriteLine(d is Base);  // output: True
        Console.WriteLine(d is Derived); // output: True
    }
}

下一個範例顯示 is 運算子考慮 Boxing 和 Unboxing 轉換,但不考慮數值轉換

int i = 27;
Console.WriteLine(i is System.IFormattable);  // output: True

object iBoxed = i;
Console.WriteLine(iBoxed is int);  // output: True
Console.WriteLine(iBoxed is long);  // output: False

如需 C# 轉換的資訊,請參閱 C# 語言規格轉換一章。

包含模式比對的型別測試

is 運算子也會對將運算式結果對模式進行測試。 下列範例示範如何使用宣告模式來檢查運算式的執行階段型別:

int i = 23;
object iBoxed = i;
int? jNullable = 7;
if (iBoxed is int a && jNullable is int b)
{
    Console.WriteLine(a + b);  // output 30
}

如需支援模式的相關資訊,請參閱模式

as 運算子

as 運算子將運算式的結果明確地轉換成給定參考或可為 Null 的實值型別。 如果無法轉換,則 as 運算子會傳回 null。 不同於轉換運算式as 運算子一律不會擲回例外狀況。

以下格式的運算式

E as T

其中 E 是會傳回值的運算式,而 T 是型別名稱或型別參數,產生的結果與下列相同

E is T ? (T)(E) : (T)null

但只會評估 E 一次。

as 運算子只考慮參考、可為 Null、Boxing 和 Unboxing 轉換。 您無法使用 as 運算子來執行使用者定義轉換。 若要這樣做,請使用轉換運算式

下列範例示範 as 運算子的用法:

IEnumerable<int> numbers = new List<int>(){10, 20, 30};
IList<int> indexable = numbers as IList<int>;
if (indexable != null)
{
    Console.WriteLine(indexable[0] + indexable[indexable.Count - 1]);  // output: 40
}

注意

如上述範例所示,您需要將 as 陳述式的結果與 null 比較,以檢查轉換是否成功。 您可以使用 is 運算子測試轉換是否成功,如果成功,便將其結果指派至新變數。

轉換運算式

格式為 (T)E 的轉換運算式會執行明確轉換,將運算式 E 的結果轉換成型別 T。 如果沒有從型別 E 轉換成型別 T 的明確轉換存在,就會發生編譯時期錯誤。 在執行階段,明確轉換可能不會成功,且轉換運算式可能會擲回例外狀況。

下列範例示範明確的數值和參考轉換:

double x = 1234.7;
int a = (int)x;
Console.WriteLine(a);   // output: 1234

int[] ints = [10, 20, 30];
IEnumerable<int> numbers = ints;
IList<int> list = (IList<int>)numbers;
Console.WriteLine(list.Count);  // output: 3
Console.WriteLine(list[1]);  // output: 20

如需支援之明確轉換的資訊,請參閱 C# 語言規格明確轉換一節。 如需如何定義自訂明確或隱含型別轉換的資訊,請參閱使用者定義轉換運算子

() 的其他用法

您也使用括號來呼叫方法或叫用委派

括弧的其他用法是調整評估運算式中作業的順序。 如需詳細資訊,請參閱 C# 運算子

typeof 運算子

typeof 運算子會取得型別的 System.Type 執行個體。 typeof 運算子的引數必須是型別名稱或型別參數,如下列範例所示:

void PrintType<T>() => Console.WriteLine(typeof(T));

Console.WriteLine(typeof(List<string>));
PrintType<int>();
PrintType<System.Int32>();
PrintType<Dictionary<int, char>>();
// Output:
// System.Collections.Generic.List`1[System.String]
// System.Int32
// System.Int32
// System.Collections.Generic.Dictionary`2[System.Int32,System.Char]

引數不得為需要中繼資料批註的型別。 範例包含下列型別:

  • dynamic
  • string? (或任何可為 Null 的參考型別)

這些型別不會直接以中繼資料表示。 這些型別包含描述基礎型別的屬性。 在這兩種情況下,您可以使用基礎型別。 您可以使用 object,而不是dynamic。 您可以使用 string,而不是string?

您也能搭配使用 typeof 運算子和未繫結的泛型型別。 未繫結泛型型別的名稱必須包含適當數目的逗號,也就是比型別參數數目少一。 下列範例顯示搭配使用 typeof 運算子和未繫結泛型型別的用法:

Console.WriteLine(typeof(Dictionary<,>));
// Output:
// System.Collections.Generic.Dictionary`2[TKey,TValue]

運算式不能作為 typeof 運算子的引數。 若要取得運算式結果執行階段型別的 System.Type 執行個體,請使用 Object.GetType 方法。

使用 typeof 運算子的型別測試

使用 typeof 運算子來檢查運算式結果的執行階段型別,是否完全符合給定型別。 下列範例示範使用 typeof 運算子和 is 運算子,進行型別檢查之間的差異:

public class Animal { }

public class Giraffe : Animal { }

public static class TypeOfExample
{
    public static void Main()
    {
        object b = new Giraffe();
        Console.WriteLine(b is Animal);  // output: True
        Console.WriteLine(b.GetType() == typeof(Animal));  // output: False

        Console.WriteLine(b is Giraffe);  // output: True
        Console.WriteLine(b.GetType() == typeof(Giraffe));  // output: True
    }
}

運算子是否可多載

isastypeof運算子無法多載。

使用者定義型別不可多載 () 運算子,但可定義可由轉換運算式進行的自訂型別轉換。 如需詳細資訊,請參閱使用者定義轉換運算子

C# 語言規格

如需詳細資訊,請參閱 C# 語言規格的下列幾節:

另請參閱