LINQ Select Statement。匿名方法返回异常

时间:2014-05-19 17:53:42

标签: c# linq task async-await

在LINQ Select语句中使用匿名方法时,匿名方法是否必须返回值?

当我执行以下操作时,我没有错误:

await Task.WhenAll(list.Select(a => doSomething(a)));

但是当我这样做时,我收到的错误是type arguments cannot be inferred from the usage

await Task.WhenAll(list.Select(a => {
    doSomething(a);
    Log("Log Something");
    UpdateUI();
}));

为什么第一个工作而第二个工作没有?

以下是doSomething方法:

private async Task doSomething(string a)
{
     HttpClient client = new HttpClient;
     // Do stuff
     string source = await client.PostAsync(a, content);
     // Extract data from source and store in text file.
}

3 个答案:

答案 0 :(得分:5)

  

在LINQ Select语句中使用匿名方法时,匿名方法是否必须返回值?

是。 Select方法的签名是:

public IEnumerable<TResult> Select<TSource, TResult>(
    IEnumerable<TSource> source, 
    Func<TSource, TResult> selector)

所以选择器必须返回一个值。

使用您的第一个代码段,return语句是隐式的。 doSomething返回一个值,该值是每个项目的投射值。

当你使用语句lambda而不是表达式lambda时,没有隐式的return语句。由于您的第二个代码块未返回任何内容,因此它与Select期望的内容不匹配。

现在,至于你的实际问题。您要做的是将每个任务投影到执行某项操作的任务中,然后在完成后写入日志并更新UI。您可以使用async lambda来执行此操作。在async lambda中,如果没有return语句,它仍然会返回Task(只是没有Result)而不是void。而这正是您想要做的,将每项任务投射到另一项任务中。

await Task.WhenAll(list.Select(async a => {
    await doSomething(a);
    Log("Log Something");
    UpdateUI();
}));

答案 1 :(得分:2)

是的,您传递给Select()的函数必须返回一个值,因为Select的目的是将一组值更改为另一组值。怎么样:

定义此方法:

private async Task DoSomethingLogAndUpdate(string a)
{
     await doSomething(a);
     Log("Log Something");
     UpdateUI();
}

然后做:

await Task.WhenAll(list.Select(a => DoSomethingLogAndUpdate(a)));

或者在没有定义单独方法的情况下执行此操作:

await Task.WhenAll(list.Select(async a => {
    await doSomething(a);
    Log("Log Something");
    UpdateUI();
}));

答案 2 :(得分:2)

第一个是简单表达式,因此该表达式的类型用作lambda的返回类型。

来自MSDN

  

一个lambda表达式,其表达式位于=&gt;的右侧。 operator被称为表达式lambda。表达式lambdas广泛用于构建表达式树(C#和Visual Basic)。 表达式lambda返回表达式的结果

(强调我的)

但是,你所拥有的是语句 lambda,这意味着为了返回一个值,你必须在lambda体中有一个return语句。