おまえは今まで書いたswitch文の数をおぼえているのか?

なんと巷では**switch式**なる便利なものが存在しているそうじゃあないか

今までのswitch"文"よりもswitch"式"の方が読みやすく、パターンマッチングとも相性がいいとのこと

C#を業務で使っているのにも関わらず最近までは知らなかった…

タイトルでお察しかとは思いますが、筆者はジョジョが好きなので
ジョジョの要素を詰め込んでさっそく使ってみます

# 今までのswitch文
まずは今まで使っていたswich文の振り返りから。
受け取った数字によって該当する部の主人公名とサブタイトルを返すメソッドです
（6部以降はあんまり知らないので5部までで許してください）
```c#
private (string, string) OldSwitch(int partNum)
{
    (string, string) result;
    switch (partNum)
    {
        case 1:
            result = ("ジョナサン・ジョースター", "ファントムブラッド");
            break;
        case 2:
            result = ("ジョセフ・ジョースター", "戦闘潮流");
            break;
        case 3:
            result = ("空条承太郎", "スターダストクルセイダーズ");
            break;
        case 4:
            result = ("東方仗助", "ダイアモンドは砕けない");
            break;
        case 5:
            result = ("ジョルノ・ジョバーナ", "黄金の風");
            break;
        default:
            throw new ArgumentException("1~5以外の数字はここに到達しない想定");
    }
    return result;
}
```

### 問題点
- 改行が多すぎる
- 毎回`break`書くのめんどくさい（`result`に代入せず`return`すれば一応防げますが）
- 頭から抜け落ちているパターンは実行時でないと気付けない

**やれやれだぜ…**

# switch式に書き換えると…
対して新しいswitch式に書き換えると以下の実装になります
```c#
 private (string, string) NewSwitch(int partNum)
{
    return partNum switch
    {
        1 => ("ジョナサン・ジョースター", "ファントムブラッド"),
        2 => ("ジョセフ・ジョースター", "戦闘潮流"),
        3 => ("空条承太郎", "スターダストクルセイダーズ"),
        4 => ("東方仗助", "ダイアモンドは砕けない"),
        5 => ("ジョルノ・ジョバーナ", "黄金の風"),
        _ => throw new ArgumentException("1~5以外の数字はここに到達しない想定"),
    };
}
```
### 嬉しい点
- 見た目すっきり
- `break`や変数への代入等、条件分岐に関係のない記述をしなくていい
- 網羅されていないパターンはコンパイラが警告を出してくれる👇
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3889500/5c01de5d-fa87-4e46-84e2-3e9ee15ce4e2.png)

**グレートですよ　こいつは！**

# 式としての利用も可能
switch式は変数の代入やメソッドの引数に直接記述することができます
例えば、`enum`の値によって別々の値を設定したいケース。
```c#
enum Character
{
    Jotaro,
    Dio,
}

var character = Character.Dio;

// 変数の代入
var stand = character switch
{
    Character.Jotaro => "スタープラチナ",
    Character.Dio => "ザ・ワールド",
};

// メソッドの引数
Console.Write(character switch
{
    Character.Jotaro => "スタープラチナ",
    Character.Dio => "ザ・ワールド",
    
});
```

# 注意点
スゴ味のあるswitch式ですが、使用上の注意点ももちろんあります

あくまでも「この値だったらこれを返す」という側面が強く、値を返さずに複数の処理を実行するパターンには向きません

例えば、以下のようにケースごとに異なる処理を複数実行する場合
```c#
// Characterは先ほどのenumを流用
private void Attack(Character character)
{
    switch (character)
    {
        case Character.Jotaro:
            this.StopTime();
            this.OraOra();
            break;
        case Character.Dio:
            this.StopTime();
            this.UseRoadRoller();
            break;
    }
}

private void StopTime() => Console.WriteLine("時よ止まれ！");
private void UseRoadRoller() => Console.WriteLine("ロードローラーだッ! ");
private void OraOra() => Console.WriteLine("オラオラオラオラオラァ！");
```
このように簡単なものであれば頑張ってswitch式で書けなくもないですが、実際のプロダクトコードではもっと複雑な処理をしていることがほとんどなので、素直にswitch文を使うのがよいでしょう

# まとめ
| 項目       | switch文                  | switch式                  |
|------------|---------------------------|---------------------------|
| **戻り値** | 不可                      | 必須                      |
| **パターン** | 定数のみ                 | 型/範囲/タプル対応        |
| **null処理** | 明示的チェック必要       | nullパターン直接記述可    |
| **網羅性** | 手動確認                  | コンパイラ警告            |
| **記述量** | 冗長                      | 簡潔                      |

書いた数を覚えていないくらい触れてきたswich文ですが、戻り値のある簡単な分岐であればここらでswitch式に乗り換えもありですね

（switch式が使用可能になったのはC#8.0からなのですが、職場で使っているバージョンには対応しておらず、私はしばらく付き合いが続きそうです…）

それでは**アリーヴェデルチ**✋

# 参考
https://learn.microsoft.com/ja-jp/dotnet/csharp/language-reference/operators/switch-expression

https://terakoya.sejuku.net/question/detail/43108

https://qiita.com/GameDevEgg/items/fc245ee18ab0961d57ba