C# 8.0のswitch式
switch式
C#のswitch
が、C# 8.0から式で使えるようになってます。いいですね。
良い例が思い浮かばないのが申し訳ないですが、このようなEnum
があるとします。
public enum DayOfWeek
{
Sunday,
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday,
}
ある日付の曜日を日本語で表示するためのswitch
を使用するとします。従来はこのように書いていました。
var dow_eng = DateTime.Today.DayOfWeek;
var dow_jpn = "";
switch ((DayOfWeek)dow_eng)
{
case DayOfWeek.Sunday:
dow_jpn = "日曜日";
break;
case DayOfWeek.Monday:
dow_jpn = "月曜日";
break;
case DayOfWeek.Tuesday:
dow_jpn = "火曜日";
break;
case DayOfWeek.Wednesday:
dow_jpn = "水曜日";
break;
case DayOfWeek.Thursday:
dow_jpn = "木曜日";
break;
case DayOfWeek.Friday:
dow_jpn = "金曜日";
break;
case DayOfWeek.Saturday:
dow_jpn = "土曜日";
break;
default:
dow_jpn = "エラー";
break;
}
Console.Write(dow_jpn);
なっが~~。これいちいちcase
とかdefault
とかbreak
とかだらだらと書かなきゃいけなくて、すごく面倒ですよね。
これがC# 8.0ではこう書けます。
var dow_eng = DateTime.Today.DayOfWeek;
var dow_jpn = (DayOfWeek)dow_eng switch
{
DayOfWeek.Sunday => "日曜日",
DayOfWeek.Monday => "月曜日",
DayOfWeek.Tuesday => "火曜日",
DayOfWeek.Wednesday => "水曜日",
DayOfWeek.Thursday => "木曜日",
DayOfWeek.Friday => "金曜日",
DayOfWeek.Saturday => "土曜日",
_ => "エラー",
};
Console.Write(dow_jpn);
すっきりしましたね。特徴としてはswitch式
なので、それ自体が文字列を返してくれます。長ったらしくcase
とかを書かずに済むのはとても良いですね。
default
に当たる処理は_
とマッチさせます。
_
が使われている場合は無視される
C#はstring
もswitch
に使用できます。その場合、case
には変数(定数)も使用できます。
では_
が既に変数(定数)として使用されている場合はどうなるでしょうか。
var lastName = "八千崎";
const string _ = "雪村";
const string KuraueHinata_last = "倉上";
const string AobaKokona_last = "青羽";
const string SaitoKaede_last = "斎藤";
const string KurosakiHonoka_last = "黒崎";
var firstName = lastName switch
{
KuraueHinata_last => "ひなた",
AobaKokona_last => "ここな",
SaitoKaede_last => "かえで",
KurosakiHonoka_last => "ほのか",
_ => "あおい",
};
Console.Write(firstName);
// 出力結果:あおい
なんと、定数としての_
とはマッチせずに、default
のキーワードとしての_
としてマッチしてしまいました。この結果、八千崎という人があおいちゃんと認識されてしまいました。これはまずい!
まぁまずないとは思いますが、_
という変数(定数)はうまくマッチングできないので使用を控えましょう。個人的にはout
引数でも特別な意味のあるキーワードなので_
という変数などは宣言できないようにしてほしいのですが、まぁ後方互換性とかもあるのでね、仕方ないですね…。
あおいちゃんとマッチングさせたくない場合は、面倒くさがらず
var lastName = "八千崎";
const string AoiYukimura_last = "雪村";
const string KuraueHinata_last = "倉上";
const string AobaKokona_last = "青羽";
const string SaitoKaede_last = "斎藤";
const string KurosakiHonoka_last = "黒崎";
var firstName = lastName switch
{
AoiYukimura_last => "あおい",
KuraueHinata_last => "ひなた",
AobaKokona_last => "ここな",
SaitoKaede_last => "かえで",
KurosakiHonoka_last => "ほのか",
_ => "そんな子おらん",
};
Console.Write(firstName);
// 出力結果:そんな子おらん
としましょう。
複数case
とのマッチは不可
ただし、複数のcase
とマッチさせることはできません。
具体的には、平日か休日かを判定したい場合、従来は
var dow_eng = DateTime.Today.DayOfWeek;
var workdayOrHoliday = "";
switch ((DayOfWeek)dow_eng)
{
case DayOfWeek.Monday:
case DayOfWeek.Tuesday:
case DayOfWeek.Wednesday:
case DayOfWeek.Thursday:
case DayOfWeek.Friday:
workdayOrHoliday = "平日";
break;
case DayOfWeek.Saturday:
case DayOfWeek.Sunday:
workdayOrHoliday = "休日";
break;
default:
workdayOrHoliday = "エラー";
break;
}
Console.Write(workdayOrHoliday);
この様に、月~金は平日、土・日は休日とまとめて指定できたのですが、新しいswitch式
ではそれができません。
var dow_eng = DateTime.Today.DayOfWeek;
var workdayOrHoliday = (DayOfWeek)dow_eng switch
{
DayOfWeek.Sunday => "休日",
DayOfWeek.Monday => "平日",
DayOfWeek.Tuesday => "平日",
DayOfWeek.Wednesday => "平日",
DayOfWeek.Thursday => "平日",
DayOfWeek.Friday => "平日",
DayOfWeek.Saturday => "休日",
_ => "エラー",
};
Console.Write(workdayOrHoliday);
と書くしかないんですね。これは嫌ですね。個人的には以下のような感じで書ければなと思っています。このコードは動きません。
var dow_eng = DateTime.Today.DayOfWeek;
var workdayOrHoliday = (DayOfWeek)dow_eng switch
{
DayOfWeek.Monday | DayOfWeek.Tuesday | DayOfWeek.Wednesday | DayOfWeek.Thursday | DayOfWeek.Friday => "平日",
DayOfWeek.Sunday | DayOfWeek.Saturday => "休日",
_ => "エラー",
};
Console.Write(workdayOrHoliday);
今後拡張されるかもしれないので、楽しみに待とうと思います。
ということでC# 8.0におけるswitch式
の備忘録でした。
おまけ
まぁ例が悪かったのでアレなんですけど、単純に日本語の曜日を取得するだけなら
var culture_jpn = CultureInfo.GetCultureInfo("ja-JP");
var dow_jpn = DateTime.Today.ToString("dddd", culture_jpn);
Console.Write(dow_jpn);
上記でできます。実行環境が日本語カルチャの設定になっているなら、カルチャの指定すら不要です。
// 実行環境が日本カルチャの場合
var dow_jpn = DateTime.Today.ToString("dddd");
Console.Write(dow_jpn);