Unity & C# 学習教材

型変換と型チェック

継承関係にある型の間で変数を代入・変換する操作をキャストと呼びます。基底クラスへの変換(アップキャスト)と派生クラスへの変換(ダウンキャスト)では、規則が異なります。

学習目標

前提知識


1. アップキャスト

書式:アップキャスト

1
基底クラス型 変数名 = 派生クラスの値;

派生クラスのインスタンスを基底クラス型の変数に代入することをアップキャストといいます。暗黙的に行えます。

1
2
3
4
5
class A { }
class B : A { }

B b = new B();
A a = b;        // アップキャスト(暗黙的)

BA を継承しているため、B のインスタンスは常に A として扱えます。


2. ダウンキャスト

書式:ダウンキャスト

1
派生クラス型 変数名 = (派生クラス型)基底クラス変数;

基底クラス型の変数を派生クラス型に変換することをダウンキャストといいます。明示的な記述が必要です。

1
2
3
4
5
class A { }
class B : A { }

A a = new B();
B b = (B)a;     // ダウンキャスト(明示的)

実体が対象の派生クラスでない場合、実行時に InvalidCastException が発生します(プログラムがその時点でエラーとなり強制停止します)。

1
2
3
4
5
6
class A { }
class B : A { }
class C : A { }

A a = new B();
C c = (C)a;     // ❌ 実行時エラー: a の実体は B であり C ではない

3. is 演算子

書式:is 演算子

1
式 is 型名
要素 説明
チェック対象の値
型名 チェックする型

is は値が指定した型であるかを bool で返します。ダウンキャスト前の確認に使えます。

1
2
3
4
5
6
7
8
class A { }
class B : A { }

A a = new B();
if (a is B)
{
    B b = (B)a;
}

4. as 演算子

書式:as 演算子

1
式 as 型名
要素 説明
変換対象の値
型名 変換先の型

as はキャストに成功すると変換後の値を返し、失敗すると null を返します。例外を発生させず null チェックで安全性を確保できる点が特徴です。

1
2
3
4
5
6
7
8
9
10
11
12
13
class A { }
class B : A
{
    public void M() { Console.WriteLine("B.M"); }
}

A a = new B();
B b = a as B;

if (b != null)
{
    b.M();
}
1
B.M

5. パターンマッチング(C# 7 以降)

この書き方は C# 7 から使えます。

書式:型パターン

1
2
3
if (式 is 型名 変数名)
{
}
要素 説明
チェック対象の値
型名 チェックする型
変数名 チェック成功時にその型として使える変数名

型チェックと変数宣言を 1 行に書けます。型が一致したとき if ブロック内で変数が有効になります。

1
2
3
4
5
6
7
8
9
10
11
class A { }
class B : A
{
    public void M() { Console.WriteLine("B.M"); }
}

A a = new B();
if (a is B b)
{
    b.M();
}
1
B.M

よくあるミス

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class A { }
class B : A
{
    public void M() { Console.WriteLine("B.M"); }
}

A a = new B();

// ❌ NG: as の結果が null の可能性を確認しないまま使用する
B b = a as B;
b.M();  // b が null の場合 NullReferenceException が発生する

// ✅ OK: null チェックを行ってから使用する
B b2 = a as B;
if (b2 != null)
{
    b2.M();
}

まとめ


理解度チェック

  1. アップキャストはなぜ明示的な記述が不要なのですか?
  2. (B)aa as B の失敗時の動作の違いを説明してください。
  3. 次のコードで a is B b が成立するとき、変数 b はどのスコープで使えますか?

    1
    2
    3
    4
    5
    
    A a = new B();
    if (a is B b)
    {
        // ...
    }
    
解答を見る
  1. 派生クラスは基底クラスのすべてのメンバーを持つため、型安全性が保証されているからです。
  2. (B)a は失敗すると InvalidCastException を発生させます。a as B は失敗すると null を返します。
  3. if ブロックの内側です。条件が成立したときのみ b が有効になります。

次のステップ

protected 修飾子 では、継承文脈で使う protected のアクセス範囲を学びます。