Code Fix

上級

SwitchExpressionException の原因と直し方

switch式が全てのパターンを網羅していないとき、コンパイラは警告を出しますが止めません。網羅されていない値が実際に渡された瞬間に実行時エラーになります。

エラーメッセージの読み方

Unhandled exception. System.Runtime.CompilerServices.SwitchExpressionException: Non-exhaustive switch expression failed to match its input.
System.Runtime.CompilerServices
名前空間 — System なら標準の基本例外です
SwitchExpressionException
例外クラス — 何が起きたか。ここを検索するのが最短です
Non-exhaustive switch expression failed to match its input.
詳細メッセージ — どの値が問題だったか
at Program.Describe(Int32 n) in Program.cs:line 3
発生箇所 — スタックトレースの先頭行

このエラーが出る典型パターン

パターン1

 1  class Program {
 2      static string Describe(int n) {
 3          return n switch {
 4              1 => "one",
 5              2 => "two",
 6          };
 7      }
 8      static void Main(string[] args) {
 9          System.Console.WriteLine(Describe(3));
                                              ^
10      }
11  }
Unhandled exception. System.Runtime.CompilerServices.SwitchExpressionException: Non-exhaustive switch expression failed to match its input. at Program.Describe(Int32 n) in Program.cs:line 3

switch式は網羅していないパターンがあると、そこに来たときだけ実行時に失敗します。コンパイラは警告は出しますが止めてはくれません。

直し方: 31 にします。

この問題を解いてみる →

広告
広告スロット(未設定)

パターン2

 1  class Program {
 2      static string Grade(int score) {
 3          return score switch {
 4              90 => "A",
 5              80 => "B",
 6              70 => "C",
 7          };
 8      }
 9      static void Main(string[] args) {
10          System.Console.WriteLine(Grade(60));
                                            ^
11      }
12  }
Unhandled exception. System.Runtime.CompilerServices.SwitchExpressionException: Non-exhaustive switch expression failed to match its input. at Program.Grade(Int32 score) in Program.cs:line 3

点数を細かく分岐させるほど、想定外の値を見落としやすくなります。_ => "..."のような既定パターンを最後に置くと防げます。

直し方: 6080 にします。

この問題を解いてみる →

パターン3

 1  class Program {
 2      static string Label(int code) {
 3          return code switch {
 4              200 => "OK",
 5              404 => "Not Found",
 6          };
 7      }
 8      static void Main(string[] args) {
 9          System.Console.WriteLine(Label(500));
                                            ^
10      }
11  }
Unhandled exception. System.Runtime.CompilerServices.SwitchExpressionException: Non-exhaustive switch expression failed to match its input. at Program.Label(Int32 code) in Program.cs:line 3

HTTPステータスコードのように種類が多い値をswitch式で扱うときほど、既定パターンの用意が重要になります。

直し方: 500200 にします。

この問題を解いてみる →

よくある誤解

警告(CS8509)が出ていても、ビルドは成功してしまいます。見た目上は正常に動くコードに見えるため、想定外の入力が来るまで気づきにくいバグです。

まとめ

SwitchExpressionExceptionは上級でつまずきやすい項目です。上の3パターンを実際に手で直すと、エラーメッセージのどこを読めばよいかが掴めます。

演習をはじめる

関連するエラー

広告
広告スロット(未設定)