🐕
【C#】switch式でswitch文を再現する
switch式の問題点
- C#のswitch式はC# 8.0で導入
- C由来の古いswitch文を置き換えていきたいけど…
- "式(expression)"なので完全にswitch文を置き換えられない
switch文を置き換えられない理由
- 式なので必ず値を戻す必要がある
- C#のswitch式は複数行の処理を書けない
- 関数呼び出しにすればできるけど…
- Proposalはある
現状できない(複数行)
/*
_ = cond switch
{
< 0 => {
// 複数行の処理A
},
> 50 => {
// 複数行の処理B
},
_ => 0,
};
*/
無理やり再現してみる
無理やり再現:パターンA
Func<T>を宣言して即時実行する
var cond = new Random().Next(0, 100);
_ = cond switch
{
< 0 => new Func<int>( () => {
// 複数行の処理A
return default;
})(),
> 50 => new Func<int>( () => {
// 複数行の処理B
return default;
})(),
_ => 0,
};
-
switch式の戻り値は利用しないので
_
に渡す -
new Func<T>
でFunc<T>
のデリゲートを作成- 型は何でもいいが、一番短い
int
で
- 型は何でもいいが、一番短い
-
最後に
()
付けて即時実行 -
引数にラムダ式を渡してその中で複数行処理
-
return default;
で戻り値を必ず返すようにする -
メリットデメリット
- メリット
- 特に何の用意もなくできる
- デメリット
- やっぱり長い…
- メリット
無理やり再現:パターンB
var cond = new Random().Next(0, 100);
//短くかける用の関数を定義する
static object F(Action<object> f) { f(null); return default; }
_ = cond switch
{
< 0 => F(_ => {
/* 複数行の処理A */
}),
> 50 => F(_ => {
/* 複数行の処理B */
}),
_ => 0,
};
- 短くかける用の関数
F()
を定義して使う - ラムダ式を短くかける(
_ => {}
)ようにF()
の引数はAction<T>
-
Action<T>
= 引数を一つとる
-
-
return default;
はF()
の中に追いやる - メリットデメリット
- メリット
- だいぶ短くかける
- デメリット
- どこでも使えるようにするにはまだ工夫がいる
- メリット
無理やり再現:パターンC
Util.csなどに短くかける関数の定義を持ってゆく
namespace MyNamespace;
public static class Util
{
public static object F(Action<object> f) { f(null); return default; }
}
コード中で指定
Program.csとかGlobalUsing.csとかに定義(C#10.0以降)
global using static MyNamespace.Util;
csprojで指定
.NET 8.0 以降
<ItemGroup>
<Using Include="MyNamespace.Util" Static="true" />
</ItemGroup>
実際に使うとき
実際に使うとき
var cond = new Random().Next(0, 100);
_ = cond switch
{
< 0 => F(_ => {
/* 複数行の処理A */
}),
> 50 => F(_ => {
/* 複数行の処理B */
}),
_ => 0,
};
- パターンBをどこからでもつかえるようにした
- コード中またはcsproj中で指定できる
- コード中で指定:C# 10.0 以降
- csprojで指定:.NET 8.0 以降
Discussion