委托可以分配给匿名方法或lambda,但不能分配给方法

时间:2017-11-23 19:14:42

标签: c# asynchronous async-await

在以下代码段中,

class Program
{
    static async Task Work()
    {
        await Task.Delay(1000);
    }

    static async Task Main()
    {
        // Action a =  Work;
        Action b = async () => await Task.Delay(1000);
        Action c =  async delegate () { await Task.Delay(1000);  };
    }
}

类型Action的委托不能分配给Work类型的方法Task,但奇怪的是可以分配给匿名方法或Task类型的lambda。 / p>

根据我的理解

  • Work
  • async () => await Task.Delay(1000)
  • async delegate () { await Task.Delay(1000); }

具有与Action不兼容的相同签名。造成这种不一致的原因是什么?

编辑:

以下lambda和匿名方法

  • async () => await Task.Delay(1000)
  • async delegate () { await Task.Delay(1000); }

可以代表ActionFunc<Task>,具体取决于作业的左侧。更准确地说,

隐式转换为Action

  • Action a = async () => await Task.Delay(1000)
  • Action b = async delegate () { await Task.Delay(1000); }

隐式转换为Func<Task>

  • Func<Task> a = async () => await Task.Delay(1000)
  • Func<Task> b = async delegate () { await Task.Delay(1000); }

下面是@ JSteward的评论吗?

2 个答案:

答案 0 :(得分:5)

首先,Action是返回类型void的代理:

public delegate void Action()

,您的方法的返回类型为Task

其次,lambda表达式创建的匿名方法的返回类型由委托的类型(Action)决定。由于委托是void,因此您正在创建void匿名方法。 Task.Delay调用的返回值将被丢弃。

此外,您假设,delegate()表达式中的匿名函数不是Task类型。它的类型为void,因为它没有return语句。如果你添加一个,它甚至都不会编译,因为你试图将它分配给void类型的委托:

Action c =  async delegate () { return await Task.Delay(1000);  };

给出错误消息

  

转换为void返回委托的匿名函数无法返回值。

答案 1 :(得分:2)

Work是一个返回类型为Task的函数,这就是为什么你不能把它“放”到Action中。

你的例子工作的唯一原因是lambda函数

() => Task.Delay(1000);

创建一个调用Task.Delay(1000)的Action。

void Function()
{
    Task.Delay(1000);
}

当你创建一个异步lambda

async () => await Task.Delay(1000);

创建一个等待Task.Delay(1000)的Action。

async void Function()
{
    await Task.Delay(1000);
}

同样适用于匿名函数。

P.S。

等待异步函数时,Task输出更改为“type”(在本例中为void)。这就是为什么如果等待Task.Delay(1000),你的返回类型就会失效。