【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 )();

これなら、やっていることは DoSomethingDoNothing かだから通るでしょう、という魂胆です。しかしこれも通りません。

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