在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.
}
答案 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
语句。