类型为Func的多播委托(具有返回值)?

Dav*_*huu 8 .net c#

我有以下代码:

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);
Run Code Online (Sandbox Code Playgroud)

输出是:

Func 1 executing
Func 2 executing
World!
Run Code Online (Sandbox Code Playgroud)

反转总和:

Func<string, string> funcSum = func2 + func1;
Run Code Online (Sandbox Code Playgroud)

给出输出:

Func 2 executing
Func 1 executing
Hello!
Run Code Online (Sandbox Code Playgroud)

我的初始测试是使用布尔返回类型完成的,返回的值也始终由最后一个函数确定.它是按预期工作的吗?我们不是在失去其他功能的回报价值吗?如果是这样,在现实世界中是否存在这些多播功能委托的用例?

Jon*_*eet 17

它是按预期工作的吗?

它至少按照规定工作.这是不是你的意图是另一回事:)从C#5规范的第15.4节 - 强调我的:

通过按顺序同步调用调用列表中的每个方法来调用其调用列表包含多个条目的委托实例.所谓的每个方法都传递给委托实例的同一组参数.如果这样的委托调用包含引用参数(第10.6.1.2节),则每个方法调用都将引用同一个变量; 通过调用列表中的一个方法对该变量的更改将对调用列表中的下一个方法可见.如果委托调用包括输出参数或返回值,则它们的最终值将来自列表中最后一个委托的调用.

下一个:

我们不是在失去其他功能的回报价值吗?

是的,此刻.

如果是这样,在现实世界中是否存在这些多播功能委托的用例?

说实话,很少.但是,您可以使用Delegate.GetInvocationList()以下方法拆分多播委托:

foreach (Func<string, string> func in funcSum.GetInvocationList())
{
    Console.WriteLine(func("!"));
}
Run Code Online (Sandbox Code Playgroud)


Xia*_*312 5

多播委托将始终返回最后一个函数的结果。因为没有预定义的方法来组合或链接T结果。

如果您想获得链上的所有结果,请尝试以下操作:

    var result = "!";
    foreach (Func<string, string> func in funcSum.GetInvocationList())
    {
        result = func(result);
    }
Run Code Online (Sandbox Code Playgroud)


小智 5

您的大多数问题都已经得到了回答,但是缺少的一件事是针对此的实际用例。这是一个:异步事件处理程序。

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)));
}
Run Code Online (Sandbox Code Playgroud)

这使类的用户可以简单地编写

myobject.X += async (sender, e) => { ... };
Run Code Online (Sandbox Code Playgroud)

但该对象仍将确保OnX在事件处理程序完成之前任务不会完成。