C/C++プログラマーは注意していただきたいのだが、それぞれのデータ型が扱う数値の範囲は言語仕様で決められている。JavaやVisual Basicではあらかじめ決まっているが、それと同じになっている。
扱える数値の上限と下限は、それぞれのデータ型のMinValueメソッドとMaxValueメソッドで取得できる。これらは、staticなメソッドなので、「System.Int16.MaxValue」というような書式で指定する。もちろん、int.MaxValueでも機能は同じである。これを用いて各データ型の上限と下限を出力するプログラムを書いてみよう。List 5-3がそれになる。
1: using System;
2:
3: namespace Sample003
4: {
5: class Class1
6: {
7: [STAThread]
8: static void Main(string[] args)
9: {
10: Console.WriteLine( "System.SByte {0}, {1}", System.SByte.MinValue, System.SByte.MaxValue );
11: Console.WriteLine( "System.Byte {0}, {1}", System.Byte.MinValue, System.Byte.MaxValue );
12: Console.WriteLine( "System.Int16 {0}, {1}", System.Int16.MinValue, System.Int16.MaxValue );
13: Console.WriteLine( "System.UInt16 {0}, {1}", System.UInt16.MinValue, System.UInt16.MaxValue );
14: Console.WriteLine( "System.Int32 {0}, {1}", System.Int32.MinValue, System.Int32.MaxValue );
15: Console.WriteLine( "System.UInt32 {0}, {1}", System.UInt32.MinValue, System.UInt32.MaxValue );
16: Console.WriteLine( "System.Int64 {0}, {1}", System.Int64.MinValue, System.Int64.MaxValue );
17: Console.WriteLine( "System.UInt64 {0}, {1}", System.UInt64.MinValue, System.UInt64.MaxValue );
18: Console.WriteLine( "System.Char {0}, {1}", (int)System.Char.MinValue, (int)System.Char.MaxValue );
19: Console.WriteLine( "System.Single {0}, {1}", System.Single.MinValue, System.Single.MaxValue );
20: Console.WriteLine( "System.Double {0}, {1}", System.Double.MinValue, System.Double.MaxValue );
21: Console.WriteLine( "System.Decimal {0}, {1}", System.Decimal.MinValue, System.Decimal.MaxValue );
22: }
23: }
24: }
このプログラムの実行結果はFig.5-3のようになる。
整数関係のデータ型については特に説明の必要もないだろう。System.Charは文字型なので、そのまま出力すると文字を出してしまう。そのため、intへのキャストを入れて、数値として出力させている(キャストについては後で説明を行う)。これを見て分かるとおり、0〜65535が格納できる。これはシフトJISではなく文字エンコーディングの一種であるUnicodeの値である。System.SingleとSystem.Doubleは浮動小数点表記の実数型で、結果は指数表示になっている。3.4028234E38とは「3.4028234掛ける10の38乗」という意味である。最後のSystem.Decimalは、高精度の計算ができる10進数表記のデータ型である。この結果からは分からないが、小数も扱うことができる。特に小数の計算を行うと、System.SingleやSystem.Doubleでは結果が狂う場合もあるが、System.Decimalならずっと正確に計算できる。その代わり、計算は遅くなる。スピードを取るか精度を取るかで選択されるべきものだろう。
変数を宣言して利用可能になったときには、Visual Basicなどでは決まった値(例えばゼロ)がすでに入っている。それに対して、Cなどでは不定(どんな値か分からない)になる。C#は、Cの流れを汲む言語であるが、この点に関しては別の立場を取っている。つまり、初期化されない変数は使われないようにするという態度である。
変数を初期化しないと、万一、値を代入する前の変数を利用するコードがある場合、実行するごとに挙動が変わる不安定なプログラムになる危険がある。また、バグを探そうにも、毎回挙動が変わるのでなかなか問題点を突き止められないということにもなる。
C#では、ローカル変数などは、値を代入する前に参照しようとするとコンパイル・エラーになる。クラスのメンバ変数などは、Visual Basicのように、変数を既定の値で初期化する。変数を必ず初期化すると、挙動が不安定になることを回避できるが、いちいち初期化すると、その分だけプログラムの実行速度が遅くなるという弊害がある。効率重視であれば変数の初期化は行わないという選択肢もあるが、安全重視なら初期化すべき、ということになる。C#は初期化するほうを選択したわけである。
初期化される値は基本的にゼロである。浮動小数点型なら0.0になる。bool型はfalseである。
実際に初期化されている例をList 5-4のプログラムで見てみよう。
1: using System;
2:
3: namespace Sample004
4: {
5: class Class1
6: {
7: private static int i;
8: [STAThread]
9: static void Main(string[] args)
10: {
11: Console.WriteLine( i );
12: }
13: }
14: }
List 5-4では、変数iに代入するコードは含まれていないが、何度実行しても、結果は必ず同じになる。実行した結果はFig.5-4のとおりである。
Copyright© Digital Advantage Corp. All Rights Reserved.