匿名代表在C#
我不能成为唯一一个厌倦了定义和命名一个委托,只需要一个委托的事情。 例如,我想在可能的其他线程的窗体中调用.Refresh(),所以我写了下面的代码:
private void RefreshForm() { if (InvokeRequired) Invoke(new InvokeDelegate(Refresh)); else Refresh(); }
我甚至不知道我必须这样做,我只是读了足够的恐惧,以至于在稍后的阶段它不起作用。
InvokeDelegate实际上是在另一个文件中声明的,但是我真的需要一个专门用于此的整个委托吗? 根本没有通用的代表吗?
我的意思是,例如,有一个笔类,但也有钢笔。 select笔,所以你不必重做整个事情。 这是不一样的,但我希望你明白我的意思。
是。 在.NET 3.5中,您可以使用Func和Action委托。 Func委托返回一个值,而Action委托返回void。 以下是types名称的样子:
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)
我不知道他们每个人为什么停下来四次,但对我来说这一直就够了。
你可以使用Action代理,如下所示:
private void RefreshForm() { if (InvokeRequired) Invoke(new Action(Refresh)); else Refresh(); }
或者,使用lambda语法:
private void RefreshForm() { if (InvokeRequired) Invoke((Action)(() => Refresh())); else Refresh(); }
最后是匿名的委托语法:
private void RefreshForm() { if (InvokeRequired) Invoke((Action)(delegate { Refresh(); })); else Refresh(); }
在这个特定的情况下,你可以(也应该)只是使用MethodInvoker来做到这一点…这就是为什么它存在。
if (InvokeRequired) Invoke(new MethodInvoker(Refresh)); else Refresh();
如果你正在做其他的事,你可以像其他人一样使用Func <T,…>或者Action <T,…>来适应你的用例。
简洁版本:
Invoke((MethodInvoker)delegate { Refresh(); });
那么你也可以放弃InvokeRequired的检查; 你可以直接调用它。 如果您需要传递参数,也可以工作,所以不需要其他参数特定的委托(与参数较less的Action委托一样好):
private void SetControlText(Control ctl, string text) { Invoke((MethodInvoker)delegate { ctl.Text = text; }); }
我真的需要一个专门的代理吗? 根本没有通用的代表吗?
定义你自己的代表真的可以使debugging更容易,只是因为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中只存在Action
和Action
,但是很容易用这些其他特殊function来为其他代理声明一个辅助类。
是的,有通用的代表。 Action<T1, T2...>
是一个通用的委托,它接受一些参数并返回任何值,而Func<T1, T2...R>
是一个通用委托,它接受一些参数并返回一个值。