为什么等待在多行而不是在一行中工作?

Why does await work on multiple lines but not in one line?

我可以让以下逻辑在 2 行中工作,但无法将其内联:

var result = await BuildNewsCategories();
x.ListBuilder = () => result.Select(x => _mapper.Map<a, b>(x)).ToList();

我的第一次尝试只是警告添加异步:

x.ListBuilder = async () => await BuildNewsCategories()
   .Select(x => _mapper.Map<a, b>(x)).ToList();

但这就是我卡住的地方,因为现在找不到 .Select

TLDR:不,你不能把它变成一个可用的单行代码,因为你有一个同步委托

此答案的其余部分针对搜索此问题时可能出现的其他问题提供额外信息和潜在解决方案。


await BuildNewsCategories() 两边没有括号意味着编译器无法知道:

  • 您要在 Task<TResult 上做 .Select 吗? 或者:
  • 您要对 Task (TResult) 的结果执行 .Select 吗?

没有括号,它认为您正试图在 Task 上调用 LINQ .Select 扩展方法,而不是实际返回的结果(“未包装”awaited结果)。

要对 Task 的结果执行 .Select,请将 await BuildNewsCategories() 括在括号中:


如果x.ListBuilderList<T>类型:

x.ListBuilder = (await BuildNewsCategories())
                .Select(x => _mapper.Map<a, b>(x))
                .ToList()

如果 x.ListBuilder 的类型是 Func<Task<List<T>>>:

x.ListBuilder = async () => (await BuildNewsCategories())
                            .Select(x => _mapper.Map<a, b>(x))
                            .ToList();

如果 x.ListBuilderFunc<List<T>> 类型,您的委托是同步的,您将无法在不阻塞异步代码的情况下获得单行代码(违背目的)。

在这种情况下,您的原始解决方案将是答案:

var result = await BuildNewsCategories();
x.ListBuilder = () => result
                      .Select(x => _mapper.Map<a, b>(x))
                      .ToList();

其他答案用圆括号解决了问题,但不是 return 代表,而是列表。

所以这将是正确的代码:

x.ListBuilder = async () => (await BuildNewsCategories())
             .Select(x => _mapper.Map<a, b>(x)).ToList();

如果 x.ListBuilderFunc<Task<List<b>>> 类型,这将起作用,因此它可以被称为 var list = await x.ListBuilder()。如果它必须是 Func<List<b>>,则不能异步调用它,您必须将 await BuildNewsCategories() 移动到单独的语句(您的第一个代码段)中。

x.ListBuilder 是一个同步委托,因此您不能将其更改为单行委托。

无论如何都应该避免阻塞。


即使你要阻止,例如:

x.ListBuilder = () => BuildNewsCategories()
   .Result
   .Select(_mapper.Map<a, b>)
   .ToList();

这会改变代码的语义,因为现在 BuildNewsCategories() 每次 调用委托时都会计算