型の変換

暗黙的型変換

暗黙的型変換は明示的に型の変換を指示することなく、自動的に型変換する仕組みです。
以下条件を満たす場合に暗黙的型変換が利用できます。

  1. 情報量の少ない型から大きい型への変換
  2. 派生型から基底型への変換
  3. インターフェース型への変換
// 1
int a = 1;
long b = a;

// 2
Hoge hoge = new Hoge();
HogeBase hogeBase = hoge();

// 3
IHoge iHoge = hoge;

例として変数への代入を示していますが、メソッドのパラメーターとして渡す場合なども同様です。

明示的型変換(キャスト)

明示的型変換はキャスト演算子を用いることで明示的に型変換する仕組みです。
以下条件を満たす場合に明示的型変換が利用できます。

  1. 情報量の大きい型から小さい型への変換
  2. 基底型から派生型への変換
  3. インターフェース型からの変換
// 1
long a = 1;
int b = (int)a;

// 2
HogeBase hogeBase = new HogeBase();
Hoge hoge = (Hoge)hogeBase;

// 3
IHoge iHoge = new Hoge();
Hoge hoge = (Hoge)iHoge;

上記の例では、キャストを外すとコンパイルエラーになります。

演算子オーバーロード

暗黙的型変換と明示的型変換は演算子オーバーロードすることで動作をカスタムマイズできます。
以下に互換性のないクラス間での型変換を可能にする演算子オーバーロードを例示します。

class Hoge
{
    public int Num { get; set; }

    // 暗黙的型変換の演算子オーバーロード
    public static implicit operator Piyo(Hoge hoge)
    {
        return new Piyo { Num = hoge.Num };
    }

    // 明示的型変換の演算子オーバーロード
    public static explicit operator Fuga(Hoge hoge)
    {
        return new Fuga { Num = (byte)hoge.Num };
    }
}

class Fuga
{
    public byte Num { get; set; }
}

class Piyo
{
    public long Num { get; set; }
}

上記の演算子定義により、以下のように型変換が可能になります。

Hoge hoge = new Hoge();
Fuga fuga = (Fuga)hoge;
Piyo piyo = hoge;

暗黙的型変換のオーバーロードは利用側で意図しない変換が行われてしまう可能性があるため、オーバーロードする場合は注意が必要です。
また、オーバーロードした演算子は後述するas・isでは使用されません。

as

{変換対象} as {変換先型名}のフォーマットで型変換することができます。
変換に失敗した場合はnullが返されます。
当然ですが、変換先型名には参照型・null許容の値型のみ指定可能です。

var hoge = new Hoge();
// 変換できない場合はfugaがnullになる。
var fuga = hoge as Fuga;

is

{検証対象} is {期待値型名}のフォーマットで型チェックが可能です。

Hoge hoge = new Hoge();
bool result = hoge is Fuga;

また、{検証対象} is {期待値型名} {変換結果格納変数}のフォーマットで型チェックと変換を行うことができます。 これはifの条件で使用可能です。

if (hoge is Fuga fuga)
{
    // ステートメント内で変数fugaが使用可能
}