C#8.0でswitch式が導入され、従来の case: break;
から =>
で書けるようになりました。
ですが、従来のswitch文では =>
が使えず、switch式を単独で使うと「割り当て、呼び出し、インクリメント、デクリメント、新しいオブジェクトの式のみがステートメントとして使用できます」のコンパイルエラーとなります。
switch式を文として使う方法は無いでしょうか?
C#
1int i = 1; 2 3// コンパイルエラー 4i switch 5{ 6 0 => //DoSomething 7 1 => //DoSomething 8 2 => //DoSomething 9 _ => //DoSomething 10}; 11 12// コンパイルエラー 13switch(i) 14{ 15 0 => //DoSomething 16 1 => //DoSomething 17 2 => //DoSomething 18 _ => //DoSomething 19}; 20 21// 値を受け取ればコンパイルは通るが、より良い書き方は無いか 22var _ = i switch 23{ 24 0 => //DoSomething 25 1 => //DoSomething 26 2 => //DoSomething 27 _ => //DoSomething 28};
switch 文を使えばいいのでは?
式である以上、戻り値は必要です。
case 0:
DoSomething();
break;
それはそうなのですが、できることならcase: break; なんて書きたくないですからね・・・
switch 式だと、各ケースで同じ型のオブジェクトを返す必要がありますが、それはいいんですか?
無理なものを求めとも無理という回答にしかならないので、
https://github.com/dotnet/csharplang/issues
ここに要望を出してみれば良いんじゃないでしょうか。
https://ufcpp.net/blog/2019/10/pickuproslyn1004/
そのうちできるようになるんでしょうかね?
今のところ不可能ということがわかりました、コメントありがとうございました。
Zuishinさん
> switch 式だと、各ケースで同じ型のオブジェクトを返す必要がありますが、それはいいんですか?
おっしゃる通り、voidが返せないですね。
何か代替となる方法はないかと考えてみましたが、switch 文以上に簡潔な記述のものは思いつきませんでした。
switch 式の戻り値だけの問題であれば、関数の中に入れて return してやれば済むことなので、拡張メソッドか何かで工夫してラムダ式の中に突っ込めば済むと思います。つまり、何らかの方法でデリゲートに変換してやれば文にできます。
ケースについては、これもやはり文を式に変えて何か戻り値を返す仕組みを作ればできそうです。
問題はラムダ式を使うとかえって記述量が増えることですね。
public static T Chain<T>(
this T source,
Action<T> action)
{
if (action == null)
throw new ArgumentNullException(nameof(action));
action(source);
return source;
}
public static TResult Chain<TSource, TResult>(
this TSource source,
Func<TSource, TResult> func)
{
if (func == null)
throw new ArgumentNullException(nameof(func));
return func(source);
}
これは私がよく使う拡張メソッドなのですが、次のように使います。
10.Chain(a => a + 20).Chain(Console.WriteLine).Chain(a => a + 30).Chain(Console.WriteLine);
これでコンソールに 30 と60 が表示されます。
見ての通り、文を式に変換しています。
また、Chain 内で Chain(a => a switch { 10 => "Foo", _ => "Bar" }) のようにスイッチ式を使うこともできます。
これを使えば、何でも式に変換できるので重宝していますが、似たような形でモナドを構成すれば戻り値については解決するんじゃないかと思いました。
回答1件
あなたの回答
tips
プレビュー