概要

前回(『プログラミング C#』 その1 C# の基礎)のつづき。ぱらぱら進めるぞー。
流し読みノート
変数宣言は型名か var で行う
Python では a = 1 だったところを C# では int a = 1; あるいは var a = 1; とする。 var はどの型であっても汎用的に使える便利くんだけど、「は?」って感じだよな。 var を使ったら型がある意味がないじゃん。だから var を使うのは以下のようなときのみだ。
// こんなの無駄だから……
List<int> numbers = new List<int>();
// var を使う。
var numbers = new List<int>();
それなら納得だ。あと「匿名型」というものに使うらしい。というか匿名型が追加されたときに var が追加されたらしいし。
ブロック
こういう書き方ができる。
{
    int a = 1;
}
{
    string a = "aaaa";
}
同じスコープにあるのに、同じ名前の変数を複数宣言できるのだ。あ、これは便利かも。名前がどうでもいい変数を表す _ なんかと組み合わせれば、コードが見やすくなりそう。
プリプロセッサディレ……ぷりぷり……え?
プリプロセッサディレクティブね。これは Python をいじってるときはまったく思いつかなかったことだけれど、コードを実行する前に機能する if 文を書く方法だ。整理すると「プリプロセッサ」が「メインのプログラムが動く前に動くもの」で、「ディレクティブ」は下に示す # から始まる実際の命令行のこと。
#if DEBUG
// DEBUG コンパイルシンボルがあるとき実行される
#elif STAGING
// STAGING コンパイルシンボルがあるとき実行される
#else
// その他のとき実行される
#endif
Visual Studio を使うと、コードを Debug や Release といった環境設定ごとにコンパイルできるから、 
#if DEBUG の中に Debug 環境でのみ実行してほしいコードを書けばいいのだ。 Python の Django でも環境ごとに設定を変えるなんてことはした(DjangoNote 3 設定ファイルを複数つくる)けれど、うーむ、こちらもなかなか分かりやすい。
肝心の DEBUG やら STAGING といった「コンパイルシンボル」は Visual Studio で設定する。プロジェクトのプロパティノードをダブルクリック > ビルドタブをクリック、から……。
if やら else の他にもプリプロセッサディレクティブはある。
// warning ディレクティブ
#warning ここに書いたメッセージがビルド時に表示されるらしいから、 TODO を書くのにいいんじゃない?
// error ディレクティブ
#if SILVERLIGHT
    #error SILVERLIGHT はサポートしてないよ!
#endif
// line ディレクティブ、よくわかんない。
#line 123 "Foo.cs"
// pragma ディレクティブは、「この変数、宣言してるけど使ってないよ」とかのコンパイラの警告を無効化する。
// 言うまでもなく、あんまり無効にしないほうがいい。
#pragma warning disable 168
int x;
// region ディレクティブは、とくになにか動作するものではないけど、 Visual Studio 上でコードを折り畳めるようになる。
// コーディングの補助にどうぞ。
#region 機能 A に関するコード
// 機能 A
#endregion
C# の型と CLR の型の対応
| C# | CLR | 範囲 | 
|---|---|---|
| byte | System.Byte | 0 ~ 255 | 
| int | System.Int32 | -2147483648 ~ 2147483647 | 
| long | System.Int64 | |
| float | System.Single | |
| double | System.Double | 
こういうふうに、 CLR が共通の型を管理してくれるから、 C# 以外の言語とも連携ができるわけね。前回おさえた CLR の意味をちゃんと理解して読めてて満足。
整数のオーバーフロー
↑にちょっと示したように、 int の限界値は 2147483647 だ。それに 1 足すと -2147483648 になる。これをオーバーフローという。このとき例外は発生しないので、いつの間にか予期せぬ状況になっちゃってるかもしれない。そんなときに checked コンテキストを使う。
int i = 2147483647;
checked
{
    // ここでロールオーバーが起こらず OverflowException が起こる。
    int j = i + 1;
    Console.WriteLine(j);
}

BigInteger
- そんな面倒なことは考えなくていい System.Numeric.BigIntegerは限界のない整数。
- System.Numericは参照追加が必要。
- メモリの許す限り巨大な整数を扱える。
- ただし組み込みデータ型ではなくクラスなので動作は遅い。
フォークスルー
C 言語だと、 switch 文で break を書かないと次の case へ自動で移るんだって。それをフォークスルーという。 C# はそれをサポートしてなくて、 goto case キーワードを使ってフォークスルーを実現するらしい。うん、より明示的にするのは賛成だ。
switch (x)
{
    case "One":
        Console.WriteLine("1");
        goto case "Two";
    case "Two":
    case "Three":
        Console.WriteLine("2 or 3");
        break;
}
ちなみに Python には switch はないけど、こういうふうに書けるよ。フォークスルーに相当するものはないと思うな……。
if x in ['One']:
    print('1')
elif x in ['Two', 'Three']:
    print('2 or 3')
その他つまみ読み
- string + intすると- intが自動で- stringに化けるんだって。それを実装するなら Python みたいに- f'string{int}'を実装したほうがいいと思うけど。- と思って調べたら、ちゃんと文字列に変数を埋め込む方法もあった。 $@"strings{int}tring"こうするんだって。
 
- と思って調べたら、ちゃんと文字列に変数を埋め込む方法もあった。 
- C# は Python のように if (リスト)で空っぽ判定とかできない。

 
       
      