При использовании анонимного метода в выражении 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.
}
При использовании анонимного метода в выражении LINQ Select анонимный метод должен возвращать значение?
Да. Подпись метода Select
:
public IEnumerable<TResult> Select<TSource, TResult>(
IEnumerable<TSource> source,
Func<TSource, TResult> selector)
поэтому селектор должен вернуть значение.
С вашим первым фрагментом кода оператор return неявно. doSomething
возвращает значение, и это значение соответствует прогнозу каждого элемента.
Когда вы используете оператор lambda, вместо выражения lambda, не существует неявного оператора возврата. Поскольку ваш второй блок кода ничего не возвращает, он не соответствует Select
запросу.
Теперь, что касается вашей реальной проблемы. То, что вы хотите сделать, - это проектировать каждую задачу в задачу, которая что-то делает, а затем записывать в журнал при ее завершении и обновлять пользовательский интерфейс. Вы можете использовать async
lambda для этого. В async
lambda, когда нет оператора return
он все равно будет возвращать Task
(только без Result
) вместо void
. И именно то, что вы хотите сделать, спроектируйте каждую задачу в другую задачу.
await Task.WhenAll(list.Select(async a => {
await doSomething(a);
Log("Log Something");
UpdateUI();
}));
Первое - простое выражение, поэтому тип этого выражения используется как возвращаемый тип лямбда.
Из MSDN:
Лямбда-выражение с выражением в правой части оператора => называется выражением лямбда. Выражения lambdas широко используются при построении деревьев выражений (С# и Visual Basic). Выражение lambda возвращает результат выражения
(Акцент мой)
Однако у вас есть оператор lambda, что означает, что для возврата значения вы должны иметь оператор return
в лямбда-теле.
Да, функция, которую вы передаете 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();
}));
doSomething
, а не после его завершения.Select
не должны иметь побочных эффектов, подобных этому.