Java プログラマのための C# 入門 (#1 プリミティブ型と制御構文)

最近 C# の勉強をしているので、JavaC# の差異をメモ程度に書いておきます。 タイトルには 「C# 入門」 と書いていますが、「Java プログラマC# を使うときに気をつけるべきこと」 という程度に解釈してください。 Java を知っていればとりあえず C# のプログラムは書けると思いますが、色々と違いがあって気をつけなければいけないところがありますので、そういった気をつけなければいけない点をまとめておこうというのがこの記事の趣旨です。

今回は、書籍と開発環境の紹介と、プリミティブ型と制御構文について書きます。

書籍と IDE

勉強に使っている書籍のは 『独習 C#』 です。 わりと分厚い本ですが初心者向けの記述が多いため、Java の経験があるプログラマであればさくさく読み進めていくことができます。 論点を明確に示しているため、初心者向けの記述が鬱陶しくなることもないですし、プログラミングの経験がほとんど無い人からある程度経験のある人まで幅広くオススメできる一冊です。

C# のプログラム開発に使用する IDEMicrosoft Visual C# 2010 Express です。 Eclipse などの経験があればすぐに使えると思います。 プログラムの実行方法だけはぱっと見ではわからなくて困るのですが、Ctrl + F5 で実行できます。

プリミティブ型

Java の整数型は基本的に符号つきですが、C# には符号なしの整数型も存在します。 また、decimal 型という財務計算用の型も存在します。

// プリミティブ型
bool    val1  = true; // true or false
byte    val2  = 0x2F; // 符号なし 8 ビット整数
char    val3  = 'd';  // 文字
decimal val4  = 0.3m; // 128 ビットの財務計算用小数点数 (リテラルは数値に m を付ける)
double  val5  = 0.3;  // 倍精度浮動小数点数
float   val6  = 1.0032e+23f; // 単精度浮動小数点数 (リテラルは数値に f を付ける)
int     val7  = 0x2399; // 符号あり 32 ビット整数
long    val8  = 0x7FFFFFFFFFFFFFFF; // 符号あり 64 ビット整数
sbyte   val9  = -0x7F; // 符号あり 8 ビット整数
short   val10 = 399;   // 符号あり 16 ビット整数
uint    val11 = 5555;  // 符号なし 32 ビット整数
ulong   val12 = 0xFFFFFFFFFFFFFFFF; // 符号なし 64 ビット整数
ushort  val13 = 0xFFFF; // 符号なし 16 ビット整数

異なる 2 つの型の数値に対して演算子を作用させる場合の暗黙の型変換については大体 Java と同じですが、いくつか注意しなければいけないこともあります。 暗黙の型変換については、以下の規則を上から順に見ていって、一番最初に該当するものが適用されます。

  1. 一方が decimal ならば、他方も decimal に変換される (他方が double、float ならエラー発生)
  2. 一方が double ならば、他方も double に
  3. 一方が float ならば、他方も float に
  4. 一方が ulong であれば、他方も ulong に (ただし、他方が sbyte、short、int、long ならばエラー発生)
  5. 一方が long ならば、他方も long に
  6. 一方が uint で、他方が sbyte、short、int の場合は両方 long に
  7. 一方が uint で、他方が上以外の場合は、他方も uint に
  8. その他の場合、両方とも int に

decimal 型や、ulong、uint については少し気をつける必要があるでしょう。

単項の演算に関して、int 型よりも小さい型が int 型に変換されるのは Java と同じです。 char 型も int 型に変換されます。 uint 型の正負を反転する演算を行った際には、long 型に変換されます。

byte b = 120;
// b = +b; // +b は int 型になるので, キャスト無しでは byte 型の変数に代入できない
uint ui = 10;
// int a = -ui; // -ui は long 型になるので, キャスト無しでは int 型の変数に代入できない

暗黙的な型指定

C# 3.0 からは、変数の型を明記せずに変数の宣言を行うことができます。 暗黙的に型を指定するためには、型の代わりに var キーワードを記述します。 暗黙的に型を指定するためには、変数の宣言と同時に初期化を行う必要があります。

// 暗黙的に val14 は int 型になる
var val14 = 200;

『独習 C#』 には、『この機能は必要なときにのみ使用し、乱用すべきではない』 と書かれています。

制御構文

制御構文に関しては、switch 文でフォールスルーできないということと、goto 文があるということが Java との大きな違いでしょう。

switch 文

C# の switch 文ではフォールスルーは禁止されています。 よって、break 文などを使って処理の流れを変えなければいけません。 ただし、後ろで述べるように goto 文で別の case ラベルに飛ぶことはできますので、フォールスルーが禁止されていても特に不便はないでしょう。

//
char c = 'd';
switch ( c ) {
    case 'a':
        Console.WriteLine( "NG : a" );
        break; // フォールスルーできない
    case 'c':
    case 'd': // 複数の case を並べることは可能
        Console.WriteLine( "OK" );
        break;
    default:
        Console.WriteLine( "NG : else" );
        break; // 一番最後にも break が必要
}
goto 文

Java とは違い、C# には goto 文があります。 逆に、Java のようにラベルを指定して多重ループから脱出することはできませんので、多重ループからの脱出には goto 文を使うと便利でしょう。

// 多重ループからの脱出
int count = 0;
while (true)
    while (true)
        while (true) {
            if (++count > 10) goto LOOP_END;
            Console.WriteLine("loop...");
        }
LOOP_END: ;

また、switch 文の中で、別の case ラベルに飛ぶのにも goto 文を使うことができます。

// swich 文のラベル間の移動
switch( c ) {
    case 'd':
        Console.WriteLine( "OK" );
        goto case 'a';
    case 'a':
        Console.WriteLine( "case 'a'" );
        goto default;
    default:
        Console.WriteLine( "default" );
        break;
    }
}

参考文献

独習 C#』 の 2 章、3 章を参考にしました。