2016-12-15 65 views
3

我有一个方法:如何在不添加不可达代码的情况下编译异步lambda?

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

我想与异步lambda表达式来调用它:

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

它的工作原理!但是如果我想要第三个lambda引发异常呢?

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

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

CS0201仅分配,调用,递增,递减和新对象的表达式可以作为陈述

我不知道它为什么会出现这个错误,但我明白为什么它不能编译 - 前两个lambda是Func<Task<int>>,而最后一个是Func<Task>。我希望它给我一个更好的编译错误,但让我们把这个问题放在一边。

如何获得编译代码?我可能不得不告诉编译器我想为第三个异步lambda生成什么类型​​的任务。我发现一个方法是指定throw声明后return声明:被丑陋和混乱除了

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

,它会生成一个编译器警告:

CS0162可达代码检测

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

此外,为什么我在上面的例子中得到一个CS0201错误?

+2

给出:既然是有效的,你想要的委托,只需将它转换为是什么? – Servy

+0

@Servy:实际的代码确实使用了等待。在第三个lambda中甚至会引发异常。这是一个精简版的代码。 –

+0

然后提供一个实际代表您的实际代码的示例。 – Servy

回答

6

问题是编译器推断你的TTask,因为最后一个lambda没有返回类型。

因此,它试图将第一个lambda分析为没有返回值,这意味着它们必须作为语句有效,而不是表达式。由于1作为一个声明是无效的,你这个奇怪的冠冕堂皇的错误。

为了使你的代码编译,明确地传递泛型类型参数:

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

example

+0

我无法移除'async',因为实际的代码在lambdas中使用await。在第三个lambda中甚至会引发异常。这是一个精简版的代码。 –

+0

即使按照原样,删除'async'会改变语义。 – Servy

+0

@AllonGuralnek:查看编辑答案。 – SLaks

2

在你的第一个例子中的拉姆达不会是Func<Task<int>>(没有上下文,这将是Action ),但它是该代理的有效lambda表达式。你为什么要摆在首位使用异步lambda表达式,你没有使用`await`

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

不完全;如果这是问题,他会得到一个无效的转换错误。因为这个推论,真正的问题在其他lambda中。 – SLaks

+0

这似乎也工作。谢谢! –

相关问题