【问题标题】:Convert IAsyncEnumerable to List将 IAsyncEnumerable 转换为 List
【发布时间】:2019-12-17 18:57:02
【问题描述】:

所以在 C#8 中我们添加了IAsyncEnumerable 接口。

如果我们有一个普通的IEnumerable,我们可以创建一个List 或几乎任何我们想要的其他集合。感谢那里的 Linq。

var range = Enumerable.Range(0, 100);
var list = range.ToList();

现在我想将我的IAsyncEnumerable 转换为List,这当然是异步的。这种情况下是否已经有 Linq 实现?如果没有,那我自己怎么转换呢?

【问题讨论】:

    标签: c# linq ienumerable c#-8.0 iasyncenumerable


    【解决方案1】:

    当然 - 您只需要 ToListAsync() 方法,它位于 System.Linq.Async NuGet package 中。这是一个完整的例子:

    项目文件:

    <Project Sdk="Microsoft.NET.Sdk">
    
      <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>netcoreapp3.1</TargetFramework>
      </PropertyGroup>
    
      <ItemGroup>
        <PackageReference Include="System.Linq.Async" Version="4.0.0" />
      </ItemGroup>
    
    </Project>
    

    代码:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    
    class Program
    {
        static async Task Main(string[] args)
        {
            IAsyncEnumerable<string> sequence = GetStringsAsync();
            List<string> list = await sequence.ToListAsync();
            Console.WriteLine(list.Count);
        }
    
        static async IAsyncEnumerable<string> GetStringsAsync()
        {
            yield return "first";
            await Task.Delay(1000);
            yield return "second";
            await Task.Delay(1000);
            yield return "third";
        }
    }
    

    【讨论】:

    • 感谢那个,有趣的是它还不是 .Net Core 3.1 框架的一部分。
    • @Twenty:作为一个单独的包,它可以很容易地在向后延伸的平台上使用。
    • @ca9163d9:“它得到了错误”并没有真正提供太多信息。我建议你用完整的minimal reproducible example 提出一个新问题。
    • @ca9163d9:正如我之前所说,请用一个完整的例子提出一个新问题——请让错误比“它失败”更清楚。
    • @db2:是的,您需要更具体地了解问题,我才能提供帮助。我建议您使用minimal reproducible example 提出一个新问题。
    【解决方案2】:

    如果您不想引入 NuGet 包,这里是(可能类似于)包中提到的扩展方法:

    public static class AsyncEnumerableExtensions
    {
        public static async Task<List<T>> ToListAsync<T>(this IAsyncEnumerable<T> items,
            CancellationToken cancellationToken = default)
        {
            var results = new List<T>();
            await foreach (var item in items.WithCancellation(cancellationToken)
                                            .ConfigureAwait(false))
                results.Add(item);
            return results;
        }
    }
    

    【讨论】:

    • 只是好奇 - 有谁知道为什么 Ian Kemp 链接的源代码在静态本地函数“Core”中定义了主要实现,然后直接调用它,而不是仅仅内联实现它?
    • @Andrew Williamson 在最近的提交中已更改。原因将是性能。它现在对参数进行一些验证。你会注意到外部函数没有被标记为异步,只有本地函数被标记。所以现在如果验证失败,我们就不用费力设置异步状态机了。
    • 为什么不想使用 nuget 包?它不是那些“阴暗”的软件包之一,而是 dotnetfoundation 支持的。
    • @JonasStensved 因为它可能会导致冲突,例如,如果它与 EF Core 一起使用。到目前为止,我在我的代码中只使用了一次ToListAsync,如果我添加 Nuget 包,我会收到很多模棱两可的错误,因为 EF Core 是同一个项目中的依赖项。
    猜你喜欢
    • 2023-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-13
    • 2010-09-06
    • 2011-11-25
    相关资源
    最近更新 更多