if 文は、条件が真のときだけコードのブロックを実行します。else if で条件を追加し、else はどの条件にも当てはまらなかった場合をすべて受け止めます。
出力:
Order 120: shipping 0
Order 75.50: shipping 4.99
Order 20: shipping 9.99
条件は上から下へ順に調べられ、最初に真になったものが採用されます。120の注文は >= 100 に一致し、>= 50 の判定には到達しません。だから最も限定的な条件を先に置きます。else if は独立したキーワードではなく、本体が別の if である else です。そのためC#には elseif も elif もありません。
条件はboolでなければならない
C#は数値、文字列、オブジェクトを真や偽として扱うことはありません。かっこの中の式は bool 型でなければなりません。
int count = 3;
if (count) // error CS0029: Cannot implicitly convert type 'int' to 'bool'
if (count > 0) // correct
if (name) // error: a string is not a bool either
if (name != null) // correct
これにより、0、""、null が暗黙のうちに偽とみなされるCやJavaScriptのバグの一群がなくなります。代わりに毎回比較を書く必要がありますが、そのおかげで次に読む人にも意図が伝わります。
&&、||、!で条件を組み合わせる
&&(かつ)、||(または)、!(否定)はブール値の判定を組み合わせます。&& と || は短絡評価します。左辺ですでに答えが決まっていなければ、右辺を実行します。
出力:
maya: welcome
invalid or banned account
invalid or banned account
omar: age 9 rejected
invalid or banned account
null を渡した呼び出しが安全なのは短絡評価のおかげです。username != null がfalseになった時点で username.Length は評価されないので、NullReferenceException は起きません。順序を username.Length >= 3 && username != null に入れ替えると、同じ呼び出しがクラッシュします。
&& は || より優先順位が高いので、a || b && c は a || (b && c) の意味になります。2つを混ぜるときは必ずかっこを付けます。コンパイラには不要でも、読む人には必要です。1文字の & と | も bool に使えますが、常に両辺を評価します。右辺に必ず起きなければならない副作用があるときだけ使います。
波かっこと1文のルール
分岐が1つの文だけなら波かっこは省略できます。省略すると、インデントがどうであれ、if に属するのは次の1文だけです。
出力:
Reorder email sent
Stock: 12
在庫は十分なのに「Reorder email sent」が表示されます。インデントに関係なく、2つ目の WriteLine は if の外にあるからです。if (x == null) return; のような1行のガードは波かっこなしで問題ありませんが、2行目が増えそうなものには付けておきます。
関連するバグに、条件の直後のセミコロンがあります。if (stock < 5); は空文で if を終わらせてしまい、その後のブロックは無条件に実行されます。コンパイラは警告CS0642 Possible mistaken empty statement で指摘します。これはエラーとして扱う価値があります。
条件の中の=と==
= は代入、== は比較です。ほとんどの型では、間違えて = と書いてもコンパイルが通りません。代入の結果は代入された値で、int は bool ではないからです。
int score = 10;
if (score = 100) { } // error CS0029: Cannot implicitly convert type 'int' to 'bool'
bool 変数では代入そのものが bool になるので、この打ち間違いはコンパイルが通ってしまいます。
出力:
Access granted
isAdmin is now True
条件が isAdmin を上書きし、その新しい値を判定しました。コンパイラは警告(CS0665、条件式内の代入は常に定数)を出しますが、ビルドは成功します。boolでは比較そのものを省きます:if (isAdmin) と if (!isAdmin) のほうが読みやすく、このような打ち間違いも起こりえません。
ネストしたifとガード節
ネストが1段深くなるごとに、読む人が頭の中で保持する条件が1つ増えます。各チェックが不正な入力を弾くものなら、正常系をすべての条件の内側にネストせず、早めにreturnします。
出力:
ordered 2 x keyboard
error: no product
error: quantity must be positive
error: insufficient balance
同じメソッドをネストで書くと、if が3段になり、本当の処理は最も内側のブロックに置かれ、末尾で3つの else 分岐がほどけていく形になります。ガード節なら、各ルールがエラーメッセージのすぐ隣にあり、最後の行が通常のケースになります。同じ考え方はループの中でも continue で使えます。
条件の中で変数を宣言する
条件の中で変数を宣言でき、その変数は if の中で使えます。よく使う形は、TryParse メソッドの out var と、is の型パターンの2つです。
出力:
42: positive number 42
abc: not a number
-7: number -7, not positive
string of length 5
TryParse は不正な入力に対して例外を投げる代わりに false を返すので、if と自然に組み合わせられます。解析メソッドの詳細は型変換のページで扱います。
別の手段を使うべき場面
- 2つの値から1つを選ぶ:条件演算子
condition ? a : bは、両方の分岐で代入するifより短く書けます。 - 1つの値で多数に分岐する:
switch文は値を定数のケースと比較し、10行のelse ifより見通しがよくなります。 - 値を結果に対応付ける:分岐の違いがデータだけなら、
Dictionaryの参照で長い連鎖を置き換えられます。
よくある質問
C#でelse ifはどう書きますか?
else if は2語で書きます:if (a) { ... } else if (b) { ... } else { ... }。条件は上から順に評価され、最初に真になった分岐だけが実行されるので、最も限定的な条件を先に置きます。elif や elseif というキーワードはありません。
C#でif (count)と書けないのはなぜですか?
C#の条件は bool 型でなければなりません。CやJavaScriptと違い、int、文字列、オブジェクトがtrueやfalseに変換されることはないので、if (count) はCS0029 Cannot implicitly convert type 'int' to 'bool' で失敗します。意図した比較を書きます:if (count > 0) や if (name != null)。
if文の条件で&&と&の違いは何ですか?
&& は短絡評価します。左辺がfalseなら右辺は評価されないので、s != null && s.Length > 0 が安全になります。2つのboolに対する & は毎回両辺を評価します。|| と | も同じです。右辺の副作用が必要な場合を除き、条件には && と || を使います。
C#のif文で波かっこは必須ですか?
必須ではありません。波かっこがなければ、if が制御するのはちょうど1つの文です。2行目をインデントしても分岐には加わらず、これは典型的なバグの原因になるので、多くのスタイルガイドはすべての分岐に波かっこを付けることを勧めています。
C#でif elseを1行で書けますか?
値を選ぶなら条件演算子を使います:string label = score >= 50 ? "pass" : "fail";。文を実行するなら if (x) DoA(); else DoB(); を1行で書くのは正しい構文ですが、波かっこ付きのブロックより読みにくく、拡張もしにくくなります。