C_Sharp-変数と型
C#のデータ型
値型と参照型
C#のデータ型には値型と参照型があります。
- 値型とは変数に直接値が格納される型であり、スタック上にデータを保持します。
- 参照型とは変数に参照情報(実体の格納先情報)が格納される型で、実体は別の場所に確保されます。参照型はヒープ上にデータを保持します。
データ型はそれぞれ以下のように分類されます。
値型 | 整数型、浮動小数点型、10 進型、論理型(bool型)、文字型、日付型、構造体、列挙体(enum) |
参照型 | 文字列型(stringクラス)、オブジェクト型、配列、クラス、インタフェース、デリゲート |
値型と参照型の動作的な特徴は以下の通りです。
- 値型は値の複製が生じるが、参照型は値を複製しない。
- 値型は間接参照が生じないので、メンバーアクセスが高速である。
- 参照型は値の複製が生じないので、変数への代入や引数渡しが高速である。
C#において両者の違いが重要になるのは、構造体とクラスを扱う場合です。
構造体(struct)は値型であり、クラス(class)は参照型なので、代入などの諸々の動作が若干異なるので注意する必要があります。
値型のデータ型
数値型
C#における数値型は以下の通りです。
- C#のint型は、他言語のように処理系に依存することなく、必ず32bit符号付きというサイズ固定になります。
- decimal型は記憶領域として128bitを使う指数表現です。高精度な金融計算などに適しているデータ型といえます。
sbyte a = 1; // 符号付き 8bit整数 (-128 to 127)
byte b = 2; // 符号なし 8bit整数 (0 to 255)
short c = 3; // 符号付き16bit整数 (-32765 to 32767)
ushort d = 4; // 符号なし16bit整数 (0 to 65535)
int e = 5; // 符号付き32bit整数 (-2147483648 to 2147483647)
uint f = 6; // 符号なし32bit整数 (0 to 4294967295)
long g = 7; // 符号付き64bit整数 (-9223372036854775808 to 9223372036854775807)
ulong h = 8; // 符号なし64bit整数 (0 ~ 18446744073709551616)
float i = 0.1; // 32bit浮動小数点(7桁)
double j = 0.2; // 64bit浮動小数点(15桁 〜 16桁)
decimal k = 0.3; // 10進小数 (28桁 〜 29桁)
文字型
文字列型は値型です。
なお、C#では文字の内部表現は「UTF-16」で統一されています。
char c = 'a'; //16bit Unicode
bool型(論理型)
bool型とは、真(true)と偽(false)の2種類の値だけを扱う最も単純な構造の型です。
主に論理演算や関係演算の結果や関数の戻り値にbool型で扱います。
bool ret; //ブーリアン値 (true / false)
日付型
C#では日付型が用意されるようになりました。
なお、日付型は値型なので、nullを代入するとエラーとなります。
DateTime dt; //DateTime(日付)型
参照型のデータ型
クラス型
C#のクラスは参照型であり、new演算子でインスタンスを生成することではじめて利用できます。
DataClass obj = new DataClass();
string型(stringクラス)
C#では文字列を文字型配列ではなく、文字列型(実際にはstringクラス)という独立した型で扱います。
また、string型は参照型であり、ヒープ上に領域を確保します。
string str = "string type";
配列型
C#における配列はC/C++と異なり、「配列型」という独立した型になります。
配列型は参照型であり、new演算子を用いてヒープに領域を確保します。
また、初期値を指定しない配列は0またはnullで自動的に初期化されます。
配列型は以下のように記述します。
int[] num_array1 = new int[16]; // int型を16個の配列で確保する。
int[] num_array2 = new int[]{1, 2, 3}; // 初期値を設定する
int buf = num_array2[0]; // 配列へのアクセスは[num]とします。
int[,] nums_array = new int[3, 4]; // 多次元配列はコンマで区切ります。
object型
object型とは、.NET Framework の System.Object クラスに基く全ての変数の基底オブジェクト型です。
object型の変数はどのような値でも格納できますが、型情報が判りづらくコードの可読性が下がるので、多用することは控えたほうが賢明です。
また、object型は参照型ですので、値型と動作が異なるため注意する必要があります。
object data1 = 123;
object data2 = null;
型指定について
暗黙的な型指定
C#では「var」キーワードを用いることで、変数の型指定を省略することができます。
var指定された変数は代入式(初期値)から「型推論」されます。
class Program
{
static void Main()
{
var x = "message"; // 文字列型になる
var y = 30; // int型になる
var z = 15.3; // double型になる
}
}
動的型付け(dynamic)
「dynamic」キーワードを用いることで、メソッド呼び出し時に型を決定(動的型付け)する変数を定義できます。
コンパイル時に型チェックが行われず、実行時に型を決定するため、実行時間がかかります。
class Program
{
static void DynamicAddition(dynamic x, dynamic y)
{
System.Console.WriteLine(x + y);
}
static void Main()
{
DynamicAddition(10, 15); // int型
DynamicAddition(10.3, 15.2); // double型
DynamicAddition("dynamic ", "valuable"); // 文字列型
}
}
サフィックス
数値リテラルの後ろにサフィックスを付加することで、型を明示することができます。
サフィックスは小文字を用いることも可能ですが、見間違いが起こりやすいので大文字にすることが慣例的です。
int i = 255;
uint u = 255U;
long l = 255L;
ulong ul = 255UL;
float f = 0.01F;
double d = 0.01D;
decimal m = 0.01M;