我有一个方法:
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错误?
答案 0 :(得分:6)
问题是编译器会将您的T
推断为Task
,因为最后一个lambda没有返回类型。
因此它尝试将第一个lambda解析为没有返回值,这意味着它们必须作为语句而不是表达式有效。由于1
作为语句无效,因此您会发现这种奇怪的错误。
要编译代码,请显式传递泛型类型参数:
MyMethod<Task<int>>(async () => 1, async () => 2, async () => { throw new Exception(); });
答案 1 :(得分:2)
你的第一个例子中的lambda不会是Func<Task<int>>
(没有上下文,它会是Action
),但它是该委托的有效lambda。因为它对你想要的委托有效,所以只需将其转换为:
MyMethod(async () => 1,
async () => 2,
(Func<Task<int>>)(async () => { throw new Exception(); }));