如何在不添加无法访问的代码的情况下编译此async lambda?

时间:2016-12-15 17:48:32

标签: c# lambda async-await c#-5.0

我有一个方法:

void MyMethod<T>(params Func<T>[] funcs) { }

我想用异步lambdas调用它:

MyMethod(async () => 1, async () => 2, async () => 3);

有效!但是如果我想让第三个lambda抛出异常呢?

MyMethod(async () => 1, async () => 2, async () => { throw new Exception(); });

上面没有编译,它给出了两个相同的错误:

  

CS0201只能将赋值,调用,递增,递减和新对象表达式用作语句

我不确定为什么会出现这个错误,但我理解为什么它无法编译 - 前两个lambdas是Func<Task<int>>而前一个是Func<Task>。我希望它能给我一个更好的编译错误,但让我们把这个问题抛在一边。

如何编译代码?我可能不得不告诉编译器我想为第三个异步lambda生成什么类型​​的任务。我找到的一种方法是在return语句后指定throw语句:

MyMethod(async () => 1, async () => 2, async () => { throw new Exception(); return 3; });

除了丑陋和令人困惑之外,它还会生成编译器警告:

  

CS0162检测到无法访问的代码

如何让编译器满意?如何避免无法访问的代码才能使其编译?是否有另一种方法来指定异步lambda返回的任务类型?

另外,为什么我在上面的例子中遇到CS0201错误?

2 个答案:

答案 0 :(得分:6)

问题是编译器会将您的T推断为Task,因为最后一个lambda没有返回类型。

因此它尝试将第一个lambda解析为没有返回值,这意味着它们必须作为语句而不是表达式有效。由于1作为语句无效,因此您会发现这种奇怪的错误。

要编译代码,请显式传递泛型类型参数:

MyMethod<Task<int>>(async () => 1, async () => 2, async () => { throw new Exception(); });

example

答案 1 :(得分:2)

你的第一个例子中的lambda不会是Func<Task<int>>(没有上下文,它会是Action),但它是该委托的有效lambda。因为它对你想要的委托有效,所以只需将其转换为:

MyMethod(async () => 1, 
    async () => 2, 
    (Func<Task<int>>)(async () => { throw new Exception(); }));