LINQ Выберите заявление. Анонимный метод возвращает исключение

1

При использовании анонимного метода в выражении 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
async-await
task

3 ответа

5

При использовании анонимного метода в выражении 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();
}));
2

Первое - простое выражение, поэтому тип этого выражения используется как возвращаемый тип лямбда.

Из MSDN:

Лямбда-выражение с выражением в правой части оператора => называется выражением лямбда. Выражения lambdas широко используются при построении деревьев выражений (С# и Visual Basic). Выражение lambda возвращает результат выражения

(Акцент мой)

Однако у вас есть оператор lambda, что означает, что для возврата значения вы должны иметь оператор return в лямбда-теле.

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();
}));
  • 0
    Это запишет в журнал и обновит пользовательский интерфейс при запуске doSomething , а не после его завершения.
  • 2
    Это будет работать, но в идеале операторы Select не должны иметь побочных эффектов, подобных этому.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню