34

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

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

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

4

6 に答える 6

52

はい。.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 つの args で停止したのかはわかりませんが、私にとっては常にそれで十分でした。

于 2009-06-10T20:53:28.823 に答える
26

次のように、使用できる Action デリゲートがあります。

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();
}
于 2009-06-10T20:50:51.980 に答える
8

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

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

他の人が答えたように、ユースケースに適合する場合は Func<T,...> または Action<T,...> を使用してください。

于 2009-06-10T21:04:33.187 に答える
5

短縮版:

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

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

private void SetControlText(Control ctl, string text)
{
    Invoke((MethodInvoker)delegate { ctl.Text = text; });
}
于 2009-06-10T20:49:40.143 に答える
2

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

独自のデリゲートを定義すると、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>

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

于 2009-06-10T20:59:22.667 に答える
1

はい、一般的なデリゲートがあります。 Action<T1, T2...>は、いくつかのパラメーターを受け取り、値を返さないFunc<T1, T2...R>ジェネリック デリゲートであり、いくつかのパラメーターを受け取り、値を返すジェネリック デリゲートです。

于 2009-06-10T20:53:57.963 に答える