web-dev-qa-db-ja.com

C#の匿名のデリゲート

デリゲートを必要とする何かを1回呼び出すだけで、デリゲートの定義と命名に飽き飽きしているのは私だけではありません。たとえば、他のスレッドからフォームで.Refresh()を呼び出したいので、次のコードを記述しました。

private void RefreshForm()
{
    if (InvokeRequired)
        Invoke(new InvokeDelegate(Refresh));
    else
        Refresh();
}

必要なのかどうかさえわからないが、後で読んだだけでは怖くて読めない。
InvokeDelegateは実際には別のファイルで宣言されていますが、私は本当にこれのために専用のデリゲート全体が必要ですか?一般的なデリゲートはまったくありませんか?
つまり、たとえば、Penクラスがありますが、Pensもあります。pen-of-choiceなので、全体を作り直す必要はありません。同じではありませんが、私が何を言っているのか理解していただければ幸いです。

34
Nefzen

はい。 .NET 3.5では、 Func および Action デリゲートを使用できます。 Funcデリゲートは値を返し、Actionデリゲートはvoidを返します。タイプ名は次のようになります。

System.Func<TReturn> // (no arg, with return value)
System.Func<T, TReturn> // (1 arg, with return value)
System.Func<T1, T2, TReturn> // (2 arg, with return value)
System.Func<T1, T2, T3, TReturn> // (3 arg, with return value)
System.Func<T1, T2, T3, T4, TReturn> // (4 arg, with return value)

System.Action // (no arg, no return value)
System.Action<T> // (1 arg, no return value)
System.Action<T1, T2> // (2 arg, no return value)
System.Action<T1, T2, T3> // (3 arg, no return value)
System.Action<T1, T2, T3, T4> // (4 arg, no return value)

彼らがなぜそれぞれ4つの引数で停止したのかはわかりませんが、常にそれで十分でした。

52
skb

次のように、使用できるアクションデリゲートがあります。

private void RefreshForm()
{
    if (InvokeRequired) Invoke(new Action(Refresh));
    else Refresh();
}

または、ラムダ構文で:

private void RefreshForm()
{
    if (InvokeRequired) Invoke((Action)(() => Refresh()));
    else Refresh();
}

最後に匿名デリゲート構文があります:

private void RefreshForm()
{
    if (InvokeRequired) Invoke((Action)(delegate { Refresh(); }));
    else Refresh();
}
26
Erik Forbes

この特定のケースでは、 MethodInvoker を使用してこれを行うことができます(すべきです)...それが存在する理由です。

if (InvokeRequired)
    Invoke(new MethodInvoker(Refresh));
else
    Refresh();

他の人が回答したように、あなたが他のことをしている場合は、Func <T、...>またはAction <T、...>を使用して、ユースケースに適合します。

8
Brian ONeil

短縮版:

Invoke((MethodInvoker)delegate { Refresh(); });

次に、InvokeRequiredのチェックを削除することもできます。そのまま呼び出すことができます。パラメーターを渡す必要がある場合にも機能するため、他のパラメーター固有のデリゲートは必要ありません(パラメーターのないアクションデリゲートでも同様に機能します)。

private void SetControlText(Control ctl, string text)
{
    Invoke((MethodInvoker)delegate { ctl.Text = text; });
}
5
Fredrik Mörk

このために専用のデリゲート全体が本当に必要ですか?一般的なデリゲートはまったくありませんか?

独自のデリゲートを定義すると、Intellisenseがパラメーターの名前を通知できるので、デバッグがより簡単になります。たとえば、次のようなデリゲートを作成します。

public delegate int UpdateDelegate(int userID, string city, string, state, string Zip);

コードを使用すると、.NETはパラメーター名やデリゲート名などを通知します。そのため、デリゲートの定義には、使用方法が正確にわからない場合に多くのコンテキストがあります。

ただし、Intellisenseを犠牲にしてもかまわない場合は、アドホックデリゲートとして使用できるSystem名前空間で定義されたデリゲートのクラスが既にあります。

Func<T>
Func<T, U>
Func<T, U, V>
Func<T, U, V, W>
Action, Action<T>
Action<T, U>
Action<T, U, V>
Action<T, U, V, W>

.NET 2.0にはActionActionのみが存在しますが、これらの種類のその他のアドホック関数に必要な残りのデリゲートでヘルパークラスを宣言するのは簡単です。

2
Juliet

はい、一般的な代理人がいます。 Action<T1, T2...>は、いくつかのパラメーターを取り、値を返さない汎用デリゲートであり、Func<T1, T2...R>は、いくつかのパラメーターを取り、値を返す汎用デリゲートです。

1
mqp