You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将IEnumerable<Task<string>>转换为IEnumerable<string>?

问题描述

我有一组作为对象ID的字符串集合,需要检查它们是否存在于数据库中。编写了如下代码:

var results = new List<string> { "123456", "654321" }
.Select(async s => {
  // 检查数据库
  return "The result";
});

得到的类型是IEnumerable<Task<string>>,但我需要的是IEnumerable<string>。我搞不懂Task是哪来的——明明lambda返回的是string啊。如果去掉lambda的async修饰符,就能得到IEnumerable<string>,但这样又没法在lambda里await数据库调用。

想搞清楚两个问题:

  1. 为什么会返回IEnumerable<Task<string>>?
  2. 怎么写代码才能得到IEnumerable<string>?
问题解答

一、为什么返回IEnumerable<Task<string>>?

只要给lambda加上async修饰符,这个委托就自动变成了异步方法,而异步方法的返回规则是固定的:

  • 如果你写了return T(比如这里的string),异步方法实际会返回Task<T>
  • 如果没有返回值(void),异步方法返回Task

简单说,async直接改变了整个委托的返回类型——不管你内部return什么,带async的方法都会把返回值包装成Task。所以Select遍历每个元素时,每个委托都返回Task<string>,最终就得到了IEnumerable<Task<string>>。

二、如何得到IEnumerable<string>?

核心是要等待所有Task<string>执行完成,提取出里面的string结果,分两种常见场景:

1. 串行执行(逐个等待)

如果不想同时发起大量数据库请求,避免压垮数据库,可以逐个await每个Task:

// 先把所有异步任务收集起来
var taskList = new List<string> { "123456", "654321" }
    .Select(async s => {
        // 这里写带await的数据库查询逻辑,比如:
        // var exists = await _dbContext.Entities.AnyAsync(e => e.Id == s);
        return $"ID {s} 的检查结果";
    })
    .ToList();

var results = new List<string>();
// 逐个等待任务完成,把结果加入列表
foreach (var task in taskList)
{
    results.Add(await task);
}

2. 并行执行(同时发起请求)

如果追求效率,想让所有数据库请求同时执行,可以用Task.WhenAll:

var tasks = new List<string> { "123456", "654321" }
    .Select(async s => {
        // 带await的数据库查询逻辑
        return $"ID {s} 的检查结果";
    });

// 等待所有任务完成,返回的results是string[],本身就实现了IEnumerable<string>
var results = await Task.WhenAll(tasks);

注意:这种方式会一次性发起所有异步请求,要考虑数据库的连接池上限,避免请求过多导致连接超时。

内容的提问来源于stack exchange,提问作者DreamingOfSleep

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 03:23:30