C Sharp/条件分岐

出典: フリー教科書『ウィキブックス(Wikibooks)』

条件分岐[編集]

if文[編集]

C#において if 文は、他のCファミリーのプログラミング言語と同様の構文を持っていますが、重要な違いの1つは条件式が必ず bool 型である点です。条件式は真偽値を評価し、条件を満たすかどうかを判定するため、必ず真偽値を返す式でなければなりません。これはC#における if 文の特性の一部であり、条件式の結果が真か偽かを明確にするために bool 型が必須とされています。

if文の例
using System;

public class IfStmtEx {
  public static void Main() {
    var n = 0.0 / 0.0;

    if (n > 0.0) {
      Console.WriteLine("n > 0.0");
    }
    else if (n < 0.0) {
      Console.WriteLine("n < 0.0");
    }
    else if (n == 0.0) {
      Console.WriteLine("n == 0.0");
    }
    else {
      Console.WriteLine($"n = {n}");
    }
  }
}
実行結果
n = NaN
構文
if-stmt := if '(' 条件式 ')' 文1 [ else 文2 ]
条件式は、bool型である必要があります[1]
文は、Console.WriteLine("n > 0.0");のような単文のほか、複文(ブロック; block)も含まれます(ここに示した例はすべて複文です)。
複文とは、{ }で0個以上の文をまとめたものです。
else if は、文法的には else節の文2が内包されるif文となったと解されます。その後のelseは直近のifと結合します。

switch文[編集]

C#の switch 文は、他のCファミリーの言語と似たような構文を持っていますが、整数だけでなく文字列などの式を使うこともできます。これにより、さまざまな条件に基づいて処理を分岐させることができます。

整数式を条件としたswitch文[編集]
switch文の例(整数式)
using System;

public class SwitchStmtEx {
  public static void Main() {
    var random = new System.Random();
    var i = random.Next(0, 16);
    switch (i) {
    case 2:
    case 3:
    case 5:
    case 7:
      Console.WriteLine($"{i}は一桁の素数です。");
      break;
    default:
      Console.WriteLine($"{i}は一桁の素数ではありません。");
      break;
    }
  }
}
実行結果(1)
2は一桁の素数です。
実行結果(2)
4は一桁の素数ではありません。
実行結果(3)
11は一桁の素数ではありません。
実行結果(4)
7は一桁の素数です。
乱数を使っているので、結果はこの通りにはなりませんが分岐の様子はわかると思います。
文字列式を条件としたswitch文[編集]
switch文の例(文字列式)
using System;

public class SwitchStmtEx2 {
  public static void Main() {
    string[] ary = new string[] {"東京都", "神奈川県", "千葉県", "埼玉県", "茨城県", "群馬県", "栃木県", "山梨県"};
    var random = new System.Random();
    var x = ary[random.Next(0, ary.Length)];
    switch (x) {
    case "栃木県":
    case "群馬県":
    case "埼玉県":
    case "山梨県":
      Console.WriteLine($"{x}は、海に面していません。");
      break;
    default:
      Console.WriteLine($"{x}は、海に面しています。");
      break;
    }
  }
}
実行結果(1)
神奈川県は、海に面しています。
実行結果(2)
東京都は、海に面しています。
実行結果(3)
山梨県は、海に面していません。
実行結果(4)
茨城県は、海に面しています。
乱数を使っているので、結果はこの通りにはなりませんが分岐の様子はわかると思います。
構文
switch-stmt := switch '(' 条件式 ')' { case 式1 ':' 文1 case 式2 ':' 文2  case 式n ':' 文n [ default ':'  ] '}'
パターンを条件としたswitch文[編集]

C# 7.0以降では、パターンを使用してより柔軟な条件付きの値のマッチングができるようになりました。これはswitch式において、様々な型や条件をパターンとして扱うことができる機能です。

パターンマッチングとは[編集]

パターンマッチングは、ある値が特定のパターンと一致するかを評価し、そのパターンに応じて処理を実行する仕組みです。switch文におけるパターンマッチングは、case節内にパターンを記述し、値がそのパターンにマッチするかどうかを評価します。

パターンの種類[編集]
型パターン
特定の型にマッチするかを判定します。
object obj = "hello";
switch (obj) {
case int i:
  // 整数型の場合の処理
  break;
case string s:
  // 文字列型の場合の処理
  break;
default:
  // その他の場合の処理
  break;
}
組合せパターン
複数の条件を組み合わせてマッチングを行います。
switch (value) {
case > 0 and < 10:
  // 0より大きく、10未満の場合の処理
  break;
case string s and(s.Length > 5):
  // 文字列かつ長さが5より大きい場合の処理
  break;
default:
  // その他の場合の処理
  break;
}
プロパティパターン
オブジェクトのプロパティに基づいてマッチングを行います。
switch (shape) {
case Circle { Radius: > 0 }:
  // 半径が0より大きい円の場合の処理
  break;
case Rectangle { Width: var w, Height: var h } when w == h:
  // 正方形の場合の処理
  break;
default:
  // その他の場合の処理
  break;
}

これらのパターンを組み合わせることで、より柔軟な条件付きの処理をswitch文で記述することができます。 パターンマッチングは、特に多様な型や条件に基づく条件分岐が必要な場合に役立ちます。

switch式[編集]

C# 8 で、switchが追加されました。

switch式の例
using System;

public class SwitchExprEx
{
	public static void Main()
	{
		string[] ary = new string[]{"春", "梅雨", "夏", "秋", "冬"};
		var random = new System.Random();
		var x = ary[random.Next(0, ary.Length)];
		var message = x switch {
			"春" => "Spring",
			"夏" => "Summer",
			"秋" => "Autumn",
			"冬" => "Winter",
			_ => throw new InvalidOperationException()
		};
		Console.WriteLine($"{x}は、英語で {message} です。");
	}
}
実行結果(1)
冬は、英語で Winter です。
実行結果(2)
秋は、英語で Autumn です。
実行結果(3)
春は、英語で Spring です。
実行結果(4)
Unhandled exception. System.InvalidOperationException: Operation is not valid due to the current state of the object.
   at SwitchExprEx.Main()
Command terminated by signal 6
乱数を使っているので、結果はこの通りにはなりませんが分岐の様子はわかると思います。
switch式は、フォールスルーしません。
構文
switch-expr :=  switch { 式1 '=>' 値1, 式2 '=>' 値2,  式n '=>' 値n [ _ '=>'  ] '}'
別解:辞書を使った例[編集]

初期化済みの辞書を使用して同じ機能を実装してみましょう。

using System;
using System.Collections.Generic;

class SwitchExprEx {
  static void Main() {
    Dictionary < string, string > seasons = new Dictionary < string, string > {
      { "春", "Spring" },
      { "夏", "Summer" },
      { "秋", "Autumn" },
      { "冬", "Winter" }
    };

    string[] keys = { "春", "梅雨", "夏", "秋", "冬" };
    var random = new Random();
    var selectedSeason = keys[random.Next(0, keys.Length)];

    if (seasons.TryGetValue(selectedSeason, out var message)) {
      Console.WriteLine($"{selectedSeason}は、英語で {message} です。");
    } else {
      throw new InvalidOperationException();
    }
  }
}

このコードでは、Dictionaryを使用して季節とそれに対応する英語名を格納し、TryGetValueメソッドを使用して選択された季節の英語名を取得しています。

switch による網羅性の担保[編集]

switch 式やswitch文と、enumを組合わせると、enumの定義するメンバーを網羅いていることの検証「網羅性の担保」が可能になります。

脚註[編集]

  1. ^ int 型などを条件式に書くとエラーになります。C#では、0を偽とはみなしません。i != 0の様に明示的に比較演算子を使いましょう