C#のキャスト(型変換)

C#では変数に「型」があり格納できる値の種類が決められています。
int型の変数にはint型の値しか入れる事ができず、実数値や文字列を入れる事は出来ません。

しかしながら、時にはint型の変数に格納された値を、double型で定義されたメソッドのパラメータに使用したいといったように型を変換したケースは存在します。
このため、C#では型を変換することが出来るようになっています。



数値の場合

数値の型はお互いに型変換が可能です。


暗黙的な変換

型を変換しても絶対に値が変わらないケースでは特別な指定をすることなく値を代入できます。
例えばbyte型は0~255の値を格納できますが、int型はそれよりも広い-2147483648~2147483647の値を格納でます。
byte型に格納された値がどのような値であったとしても、確実にint型へ変換して格納する事ができます。
byte numB;
int  numI;

numB = 10;
numI = numB;            // 暗黙的な変換


明示的な変換

型を変換する時、情報が失われる可能性がある場合には暗黙的な変換はできません。
例えばdouble型の値をint型に変換しようとすると小数点以下の値が格納できません。
情報が失われる可能性がある事を分かったうえでそれでも変換を行いたい場合は、開発者がその意思を明示する事で変換する事ができます。
これをキャストと呼びます。
明示的な変換は、変換後の型をカッコで囲んで変数の前に指定します。
int  numI;
byte numB;

numI = 10;
numB = (byte)numI;      // 明示的な変換

情報が失われる場合の挙動は以下の通りです。
  • 変換先の型に収まらない部分が上位ビットから破棄されます
  • 実数値を整数値に変換すると小数点以下は切り捨てられます
  • doubleをfloatに変換すると最も近い値に丸められ、floatで表現できないほど小さいと0に、大きいと無限になります

※コンパラオプションの設定に「演算のオーバーフローおよびアンダーフローをチェック」(-checkedオプション)があります。
※このオプションが付けられている場合、情報が失われる変換を行うと例外(OverflowException)がスローされます。



暗黙的/明示的変換一覧

元の型◎=暗黙的に変換できる型
△=明示的に変換できる型
sbytebyteshortushortintuintlongulongfloatdoubledecimal
sbyte  
byte  
short  
ushort  
int  
uint  
long  
ulong  
float  
double  
decimal 



クラスの場合

継承関係にあるクラスは型変換が可能です。
また、インターフェースを実装しているクラスは、そのインターフェース型へ型変換することができます。


暗黙的な変換

派生クラスから基底クラスへの型変換は特別な指定をすることなく代入できます。
このような型変換をアップキャストと呼びます。
class TestClass1
{
}

class TestClass2 : TestClass1
{
}

class TestClass3 : TestClass2
{
}

class Program
{
    public static void Main()
    {
        TestClass3 c3 = new TestClass3();
        TestClass2 c2 = c3;                  // 基底クラスへ暗黙的変換
        TestClass1 c1 = c3;                  // 基底クラスへ暗黙的変換
    }
}

インターフェースを実装しているクラスは、そのインターフェース型への変換も暗黙的に行えます。
interface TestInterface
{
}

class TestClass : TestInterface
{
}

class Program
{
    public static void Main()
    {
        TestClass     c = new TestClass();
        TestInterface i = c;                  // インターフェースへ暗黙的変換
    }
}


明示的な変換

基底クラスから派生クラスへの型変換は暗黙的な変換はできません。
派生クラスへ変換する為には、変換先のクラス(もしくはその派生クラス)のインスタンスでなければなりません。
変換できない可能性がある事を分かったうえでそれでも変換を行いたい場合は、開発者がその意思を明示する事で変換する事ができます。
このような派生クラスへの型変換をダウンキャストと呼びます。

明示的な変換は、変換後の型をカッコで囲んで変数の前に指定します。
変換できなかった場合には例外(InvalidCastException)がスローされます。
class TestClass1
{
}

class TestClass2 : TestClass1
{
}

class TestClassEx : TestClass1
{
}

class Program
{
    public static void Main()
    {
        try
        {
            TestClass2  c2 = new TestClass2();
            TestClass1  c1 = c2;                  // 基底クラスへ暗黙的変換
        
            TestClass2  c2work = (TestClass2)c1;  // 派生クラスへ明示的変換(インスタンスはTestClass3で作られているから変換できる)
            TestClassEx cex    = (TestClassEx)c1; // 派生クラスへ明示的変換(インスタンスはTestClassExではないので変換できない!)
                                                  // 例外(InvalidCastException)がスローされる
        }
        catch (InvalidCastException e)
        {
        }
    }
}


コメント