anonymous delegates in C#

自古美人都是妖i 提交于 2019-11-29 19:33:44
skb

Yes. In .NET 3.5 you can use Func and Action delegates. The Func delegates return a value, while Action delegates return void. Here is what the type names would look like:

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)

I don't know why they stopped at 4 args each, but it has always been enough for me.

There's the Action delegate you could use, like so:

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

Or, with lambda syntax:

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

Finally there's anonymous delegate syntax:

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

In this specific case you can (and should) just use MethodInvoker to do this... that is why it exists.

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

If you were doing something else you could, as others have answered use Func<T,...> or Action<T,...> if they fit your use case.

Short version:

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

Then you can also drop the check of InvokeRequired; you can just call it as it is. Works also if you need to pass parameters, so there is no need for other parameter-specific delegates (works just as well with the parameter-less Action delegate as well):

private void SetControlText(Control ctl, string text)
{
    Invoke((MethodInvoker)delegate { ctl.Text = text; });
}

Do I really need an entire delegate dedicated just for this? aren't there any generic delegates at all?

Defining your own delegates can really make debugging easier, if only because Intellisense can tell you the names of your parameters. For example, you write a delegate like this:

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

When you use it code, .NET will inform you of the parameter names, delegate name, etc, so there's a lot of context right in the delegate definition if you aren't sure exactly how something is used.

However, if you don't mind sacrificing Intellisense, there is already a class of delegates definined in the System namespace which can be used as ad-hoc delegates:

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>

Only Action and Action exist in .NET 2.0, but its easy enough to declare a helper class with the remaining delegates you need for these kind of miscellaneous ad hoc functions.

Yes, there are generic delegates. Action<T1, T2...> is a generic delegate that takes some parameters and returns no value, and Func<T1, T2...R> is a generic delegate that takes some parameters and returns a value.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!