25

C#でラムダ式でオプションの引数(デフォルトパラメータ)を使用する方法はありますか? 私はドキュメントを読みましたが、どちらかと言えば何も言えません。

たとえば、オプションの引数を使用してデフォルト値を指定する単純なメソッドを次のように定義できます。

void MyMethod(string arg = "default-value")
{ 
    Console.WriteLine(arg);
}

私が知りたいのは、ラムダ式を使用して同じことができるかどうかです。

// gives a syntax error
Action<string> MyMethod = (arg = "default") => Console.WriteLine(arg);

デリゲートを使用してデフォルト値を持つオプションのパラメーターで作業することはできますが、これは少し不器用に思えます。

delegate void MyDelegate(string arg = "default");
MyDelegate MyMethod = arg => Console.WriteLine(arg);

または、ラムダ本体のパラメーターを確認することもできます...

 Action<string> MyMethod = (arg) => Console.WriteLine(string.IsNullOrEmpty(arg) ?
                                    "default" :
                                    arg);

しかし、これもまた少し不器用に思えます。

オプションのパラメータを使用して、C#のラムダ式でデフォルト値を設定することは可能ですか?

4

2 に答える 2

28

いいえ。呼び出し元 (デリゲートを呼び出すコード) はラムダ式を "認識" しないため、そこで既定のパラメーターを指定しても意味がありません。呼び出し元が見るのはデリゲートだけです。たとえば、あなたの場合、呼び出し元のコードは知っているだけAction<string>です-ラムダ式で指定されたデフォルト値を提供するためにコンパイラーはどのように知っているのでしょうか?

物事がどのようにトリッキーになるかの例として、これ実行可能かどうか想像してみてください。次に、次のコードを検討してください。

Action<string> action;
if (DateTime.Today.Day > 10)
{
    action = (string arg = "boo") => Console.WriteLine(arg); 
}
else
{
    action = (string arg = "hiss") => Console.WriteLine(arg);
}
action(); // What would the compiler do here?

引数は呼び出しサイトでコンパイラによって提供されることに注意してください。では、最終行で何をすべきでしょうか?

これは、インターフェースと実装を持つことに少し似ています。インターフェースにデフォルトのパラメーターがあれば、それで問題ありません。実装のみにある場合は、特定の実装を知っている発信者だけがそれを見ることができます。ラムダ式の場合、呼び出し元が使用する目に見える実装は実際にはありません。デリゲート シグネチャだけがあります。

于 2013-01-10T01:14:41.980 に答える
4

ラムダは、割り当てられたデリゲートの署名が何であれ一致します。デリゲートに割り当てられていないと、ラムダはコンパイルできません。

デリゲートにオプションの引数が含まれている場合、そのデリゲートを使用すると、オプションで引数を指定できます。デリゲートがそうでない場合、そのデリゲートの使用では引数を省略できません。

Actionおよびデリゲートは非常に便利で、Funcほとんどの署名を表すことができますが、オプションの引数を持つ署名を表すことはできません。そのためには、別のデリゲート定義を使用する必要があります。

Action特に特別なわけではありませんが、これらは誰もが使用する 2 つのデリゲートにすぎないため、細かいことごとにFunc独自のデリゲートを作成する必要はありません。

于 2013-01-10T01:27:56.327 に答える