概要
前回(『プログラミング 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 (リスト)
で空っぽ判定とかできない。