C#中的匿名代理

Nef*_*zen 33 c# delegates anonymous-methods

我不能成为唯一一个厌倦了定义和命名委托只需要一个需要委托的东西的人.例如,我想从可能的其他线程调用表单中的.Refresh(),所以我编写了这段代码:

private void RefreshForm()
{
    if (InvokeRequired)
        Invoke(new InvokeDelegate(Refresh));
    else
        Refresh();
}
Run Code Online (Sandbox Code Playgroud)

我甚至不确定我必须这样做,我只是读得足以害怕它在以后的某个阶段不起作用.
InvokeDelegate实际上是在另一个文件中声明的,但是我真的需要一个专门用于此的整个委托吗?根本没有任何通用代表?
我的意思是,例如,有一个Pen类,但也有Pens.选择笔,所以你不必重拍整个事情.它不一样,但我希望你理解我的意思.

skb*_*skb 52

是.在.NET 3.5中,您可以使用FuncAction委托.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)
Run Code Online (Sandbox Code Playgroud)

我不知道他们为什么每次停在4个args,但对我来说一直都足够了.

  • 该框架的下一个版本将包括四个以上参数的Func和Action. (10认同)
  • 4不是具体的规则,但过去你应该至少考虑以某种方式组合参数. (2认同)

Eri*_*bes 26

您可以使用Action委托,如下所示:

private void RefreshForm()
{
    if (InvokeRequired) Invoke(new Action(Refresh));
    else Refresh();
}
Run Code Online (Sandbox Code Playgroud)

或者,使用lambda语法:

private void RefreshForm()
{
    if (InvokeRequired) Invoke((Action)(() => Refresh()));
    else Refresh();
}
Run Code Online (Sandbox Code Playgroud)

最后是匿名委托语法:

private void RefreshForm()
{
    if (InvokeRequired) Invoke((Action)(delegate { Refresh(); }));
    else Refresh();
}
Run Code Online (Sandbox Code Playgroud)

  • 这是一篇非常有用的帖子. (5认同)
  • 奇怪的是,第二个和第三个语法不起作用,说它无法将其转换为System.Delegate,因为它不是委托类型.但是,动作绝对是我想要的. (2认同)
  • 将lambda和匿名委托转换为Action就可以了.对困惑感到抱歉. (2认同)

Bri*_*eil 8

在这种特定情况下,您可以(并且应该)只使用MethodInvoker来执行此操作...这就是它存在的原因.

if (InvokeRequired)
    Invoke(new MethodInvoker(Refresh));
else
    Refresh();
Run Code Online (Sandbox Code Playgroud)

如果你正在做其他事情你可以,正如其他人已经回答使用Func <T,...>或Action <T,...>如果它们适合你的用例.


Fre*_*örk 5

精简版:

Invoke((MethodInvoker)delegate { Refresh(); });
Run Code Online (Sandbox Code Playgroud)

然后你也可以去掉 InvokeRequired 的检查;你可以直接调用它。如果您需要传递参数,也可以使用,因此不需要其他特定于参数的委托(也适用于无参数的 Action 委托):

private void SetControlText(Control ctl, string text)
{
    Invoke((MethodInvoker)delegate { ctl.Text = text; });
}
Run Code Online (Sandbox Code Playgroud)

  • @Brian:你的意思是这样的: Invoke(new MethodInvoker(delegate { ctl.Text = text; })); ? 据我所知,它产生的 IL 代码与我上面的代码完全相同,所以我猜这取决于个人喜好。 (2认同)