【C#】戻り値がvoidなメソッドで、式形式メンバー+三項演算子を使う
できるのかな?と思って興味本位でなんやかんややってみたのでメモです。
次のようなメソッドがあるとします。
void DoSomething()
{
// 何らかの処理
}
void DoSomethingIfNeeded(bool isNeeded)
{
if (isNeeded)
DoSomething();
}
この時、DoSomethingIfNeeded
をシンプルに式形式メンバーで書きたいと思いました。イメージとしてはこんな感じ。
void DoSomethingIfNeeded(bool ifNeeded)
=> isNeeded ? DoSomething()
: null;
上記コードはコンパイルが通りません。void
なのに null
を返しているからです。
だったら処理のない DoNothing
的なメソッドを実行させれば良いのでは?と思い、次のように書いてみました。
void DoNothing()
{
return;
}
void DoSomethingIfNeeded(bool isNeeded)
{
isNeeded ? DoSomething()
: DoNothing();
}
しかしこれもコンパイルエラーになります。
CS0201: 代入、呼び出し、インクリメント、デクリメント、新しいオブジェクトの式のみがステートメントとして使用できます
なるほど…。それなら三項演算子には、どのメソッドを呼び出すかの判定だけをしてもらえばいいのでは?
ということで下記のように書いてみました。
void DoSomethingIfNeeded(bool isNeeded)
=> ( isNeeded ? DoSomething : DoNothing )();
これなら、やっていることは DoSomething
か DoNothing
かだから通るでしょう、という魂胆です。しかしこれも通りません。
CS0149: メソッド名が必要です
そうですか…。
いやいやおかしいでしょ、実行すべきメソッドを決定しているのに、メソッド名が必要なのは変では?と思い調べてみたところ、以下の記事にたどり着きました。
僕はね、voidが戻りの関数を三項演算子みたいに使いたかっただけなんだ
https://qiita.com/vranometria/items/cfe6f282d7973ae7f52b
キャスト…。どちらも Action
であることは明らかだと思うのだけど、明示的なキャストが必要なのか…。何故…。
キャストを入れてみます。
void DoSomethingIfNeeded(bool isNeeded)
=> ( isNeeded ? (Action)DoSomething : DoNothing )();
これでコンパイルが通りました。
あとは、何もしない処理にわざわざ DoNothing
という名前を付ける必要もないので匿名化します。
void DoSomethingIfNeeded(bool isNeeded)
=> ( isNeeded ? (Action)DoSomething : () => { } )();
これで一応、当初の目的は達成できました。DoSomething
に簡単な処理を入れて実行してみます。
void DoSomething()
{
Console.WriteLine("hoge");
Console.WriteLine("fuga");
}
void DoSomethingIfNeeded(bool isNeeded)
=> ( isNeeded ? (Action)DoSomething : () => { } )();
DoSomethingIfNeeded(true);
Console.WriteLine("piyo");
// hoge
// fuga
// piyo
DoSomethingIfNeeded(false);
Console.WriteLine("piyo")
// piyo
できました。キャストが必要な理由は勉強が必要。
参考
僕はね、voidが戻りの関数を三項演算子みたいに使いたかっただけなんだ
https://qiita.com/vranometria/items/cfe6f282d7973ae7f52b
Expression-bodied members (C# programming guide)
https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/statements-expressions-operators/expression-bodied-members