型テスト演算子とキャスト式 - isastypeof、casts

これらの演算子と式で型チェックまたは型変換を実行します。 is 演算子を使って、式のランタイム型と指定された型の間に互換性があるかどうかを確認します。 as 演算子を使って、式のランタイム型と指定された型の間に互換性がある場合、指定された型に式を明示的に変換します。 キャスト式を使って、ターゲット型への明示的な変換を実行します。 typeof 演算子を使うと、型の System.Type インスタンスを取得できます。

is 演算子

is 演算子では、式の結果のランタイム型と指定された型の間に互換性があるかどうかが調べられます。 is 演算子を使用すると、パターンに対する式の結果もテストされます。

is 型テスト演算子を使用する式の形式は次のとおりです

E is T

E は値を返す式であり、T は型または型パラメーターの名前です。 E を匿名メソッドまたはラムダ式にすることはできません。

is 演算子からは、式の結果が null 以外で、次のいずれかの条件が満たされているとき、true が返されます。

  • 式の結果のランタイム型は T です。

  • 式の結果のランタイム型は T 型から派生するか、インターフェイス T を実装するか、または、それから T への暗黙的な参照変換が別に存在します。

  • 式の結果のランタイム型は、基になる型 T を持つ Null 許容値型です。また、Nullable<T>.HasValuetrue です。

  • 式の結果のランタイム型から T 型までに、ボックス化変換またはボックス化解除変換が存在します。

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 演算子では、ボックス化変換とボックス化解除変換は考慮されますが、数値変換は考慮されません。

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# 言語仕様の「Conversions (変換)」の章をご覧ください。

パターン マッチングを使用する型テスト

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 が評価されるのは 1 回だけです。

as 演算子では、参照、null 許容、ボックス化、およびボックス化解除の各変換だけが考慮されます。 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# 言語仕様の「Explicit conversions (明示的な変換)」セクションをご覧ください。 カスタムの明示的または暗黙的な型変換を定義する方法については、「User-defined conversion operators」(ユーザー定義の変換演算子) を参照してください。

() の他の使用方法

かっこは、メソッドまたはデリゲートを呼び出すときにも使います。

他には、式に含まれる演算を評価する順序を調整する場合にもかっこを使います。 詳細については、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 許容参照型)

これらの型は、メタデータで直接表現されません。 これらの型には、基になる型を記述する属性が含まれます。 どちらの場合も、基になる型を使用できます。 dynamic の代わりに、objectを使用できます。 string? の代わりに、stringを使用できます。

バインドされていないジェネリック型で typeof 演算子を使うこともできます。 バインドされていないジェネリック型の名前には、適切な数のコンマが含まれる必要があります。これは、型パラメーターの数より 1 だけ少ない数です。 次の例では、バインドされていないジェネリック型での 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# 言語仕様」の次のセクションを参照してください。

関連項目