型変換
暗黙の型変換
全てのデータには型が存在します。データ型によって、コンパイラはデータをどのように操作できるのかを判断します。例えば、数値であれば計算できますが、文字列は計算できません。その代わり、文字列は結合や検索といった操作を提供します。
同じ数値でも、整数と浮動小数点数は異なりますし、32 ビット型と 64 ビット型では扱える数の大きさや精度が異なります。符号付きの整数型であれば負数を表せますが、符号なしの整数型は負数を表現しません。
問題は、式の中で異なるデータ型が組み合わされた時です。異なる型の値を計算するには、データ型を一致させなければなりません。では、符号付きの整数と符号なしの整数による算術演算や、整数と実数が入り混じった演算が行われると、どうなるでしょう。
コンパイラは型の異なる値の演算を発見すると、一方の項を暗黙的に変換し、共通の型にしてから演算させます。これを暗黙の型変換(Implicit conversions)と呼びます。この時の変換は、定められた変換規則によって処理されるため、プログラマはそれを知っておく必要があります。
異なる数値型の値を演算しようとすると、サイズが大きいほうの型に他方を変換するのが基本です。サイズの昇格はデータを失う可能性がなく安全に変換できます。逆に、サイズを縮小する変換は、ビットを切り捨てる必要があるため、データの一部を失う可能性があります。データを損失する可能性のある処理は、暗黙的に行われることはありません。
具体的な暗黙の数値変換には、以下の組み合わせが考えられます。
元の型 | 暗黙的に変換できる型 |
---|---|
sbyte | short, int, long, float, double, decimal |
byte | short, ushort, int, uint, long, ulong, float, double, decimal |
short | int, long, float, double, decimal |
ushort | int, uint, long, ulong, float, double, decimal |
int | long, float, double, decimal |
uint | long, ulong, float, double, decimal |
long | float, double, decimal |
ulong | float, double, decimal |
char | ushort, int, uint, long, ulong, float, double, decimal |
float | double |
例えば byte 型の変数と int 型の変数を式の中で組み合わせると、暗黙の型変換によって byte 型の値が int 型に変換されて計算されます。この変換で情報が失われることはないので、普段は意識する必要はないでしょう。
class Test { static void Main() { double x = 3.24; int y = 5; System.Console.WriteLine(x + y); } }
このプログラムでは double 型と int 型の変数を加算しています。暗黙の型変換によりエラーが発生することもなく予想した結果を得られます。式が評価されたとき int 型の値が double 型に昇格し、その上で加算処理されていることがわかります。
キャスト式と明示的な型変換
暗黙の型変換による恩恵が受けられない場合もあります。 基本的に short から int へ変換する拡張変換は暗黙の型変換が発生します。
short x = value; int y = x;
上記の式において value が整数リテラルや short 型の変数であれば、この代入式は問題なくコンパイルができます。また、short 型から int 型への型変換は、整数の表現範囲が広くなるだけなのでデータが失われるようなことはありません。暗黙に型変換しても、それが何らかのバグを誘発させる可能性はありません。
しかし、逆に int 型を short 型に変換するような縮小変換は問題があります。もし int 型の変数を short 型に代入しようとするとコンパイルエラーが発生します。これは、整数の表現できる範囲が狭まり、上位ビットのデータが失われる可能性があるためです。
このように、情報が欠如する可能性のある変換は暗黙的に変換できません。int 型のようなより大きいデータ型から short 型のようなより小さいデータ型に変換するには、キャスト式(Cast expressions)を使って明示的な型変換を行います。キャスト式も単項演算子の一種なのでキャスト演算子と呼ぶこともあります。
( 型 ) 式
キャスト式では丸かっこ ( ) の中に変換先となる型を指定し、その後に変換する値となる式を指定します。
class Test { static void Main() { ushort us = 0xFFFF; byte sb = (byte)us; System.Console.WriteLine("ushort = " + us); System.Console.WriteLine("byte = " + sb); } }
このプログラムは ushort 型の us 変数を byte 型に縮小変換しています。 us の値は符号なし 16bit で 1111 1111 1111 1111 となっています。これを 8bit の byte 型にキャストすると、上位 8bit が失われ、残りの下位 8bit だけが代入されます。よって sb 変数に保存される値は 10 進数で 255 となります。