我有以下代码:
Func<string, string> func1 = (param) =>
{
Console.WriteLine("Func 1 executing");
return "Hello" + param;
};
Func<string, string> func2 = (param) =>
{
Console.WriteLine("Func 2 executing");
return "World" + param;
};
Func<string, string> funcSum = func1 + func2;
string funcResult = funcSum("!");
Console.WriteLine(funcResult);
输出为:
Func 1 executing
Func 2 executing
World!
求和逆:
Func<string, string> funcSum = func2 + func1;
给出输出:
Func 2 executing
Func 1 executing
Hello!
我的初始测试是使用布尔返回类型完成的,并且返回值也总是由最后一个函数确定。它是否按预期工作?难道我们没有丢失其他函数的返回值吗?如果是这样,在现实世界中是否有这些多播委托功能的用例?
是否按预期工作?
至少按指定的方式工作。不管这是不是你想要的,那就是另一回事了:)从c# 5规范的15.4节开始——我强调一下:
下:在调用列表中包含多个条目的委托实例的调用中,将按照顺序同步调用调用列表中的每个方法。每个被调用的方法都被传递给与委托实例相同的一组参数。如果这样的委托调用包含引用参数(§10.6.1.2),则每个方法调用将使用对同一变量的引用进行;调用列表中的一个方法对该变量的更改将对调用列表中较低位置的方法可见。如果委托调用包含输出参数或返回值,它们的最终值将来自列表中最后一个委托的调用。
我们不是失去了其他函数的返回值吗?
是的,现在。
如果是这样,在现实世界中是否有这些多播函数委托的用例?
老实说,很少。但是,您可以使用Delegate.GetInvocationList()
:
foreach (Func<string, string> func in funcSum.GetInvocationList())
{
Console.WriteLine(func("!"));
}
你的大部分问题都已经得到了回答,但有一件事是缺失的,这是一个真实的用例。这里有一个:异步事件处理程序。
public delegate Task AsyncEventHandler(object sender, EventArgs e);
public event AsyncEventHandler X;
public async Task OnX(EventArgs e) {
// ...
var @event = X;
if (@event != null)
await Task.WhenAll(
Array.ConvertAll(
@event.GetInvocationList(),
d => ((AsyncEventHandler)d)(this, e)));
}
这允许类的用户简单地写
myobject.X += async (sender, e) => { ... };
,但对象仍然会确保OnX
的任务不会完成,直到事件处理程序的任务完成。
组播委托将始终返回最后一个函数的结果。因为没有预定义的方式来组合或链接T
结果。
如果你想获得所有的结果,试试这个:
var result = "!";
foreach (Func<string, string> func in funcSum.GetInvocationList())
{
result = func(result);
}