添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
睡不着的橡皮擦  ·  IllegalArgumentExcepti ...·  1 周前    · 
淡定的楼梯  ·  老毛子 padavan ...·  3 周前    · 
急躁的冰棍  ·  190813-Influx ...·  3 月前    · 
忐忑的毛衣  ·  软件安装 - EXScan H·  4 月前    · 
失望的斑马  ·  Database Finder·  5 月前    · 
  • ASP.NET Core Identity Series
  • IdentityServer4, OAuth, OIDC Series
  • Angular with ASP.NET Core Identity
  • Blazor WebAssembly
  • .NET Collections
  • SOLID Principles in C#
  • ASP.NET Core Web API Best Practices
  • Top REST API Best Practices
  • Angular Development Best Practices
  • 10 Things You Should Avoid in Your ASP.NET Core Controllers
  • C# Back to Basics
  • C# Intermediate
  • Design Patterns in C#
  • Sorting Algorithms in C#
  • Docker Series
  • Angular Series
  • Angular Material Series
  • HTTP Series
  • About Us
  • Archives
  • Our Editors
  • Leave Us a Review
  • Code Maze Reviews
  • Contact Us
  • Want to build great APIs? Or become even better at it? Check our Ultimate ASP.NET Core Web API program and learn how to create a full production-ready ASP.NET Core API using only the latest .NET technologies. Bonus materials (Security book, Docker book, and other bonus files) are included in the Premium package!

    In this article, we will learn how to convert IAsyncEnumerable to a List in C#. We’ll talk about some practical reasons for this conversion and explore the common method for achieving it.

    To download the source code for this article, you can visit our GitHub repository .

    So without wasting time, let’s get started.

    The Reason to Convert IAsyncEnumerable to List

    The IAsyncEnumerable<T> interface, introduced in C# 8, offers a powerful tool for on-demand data delivery, enhancing efficiency in data processing. However, there are scenarios where converting it to a List<T> is not only necessary but also beneficial.

    Support Code Maze on Patreon to get rid of ads and get the best discounts on our products!
    Become a patron at Patreon!

    Let’s delve into some typical situations that necessitate this conversion.

    One of the primary reasons for this conversion involves the need to process entire datasets immediately . This is particularly relevant when performing calculations, aggregations, or when the data needs to be fed into another synchronous operation. By converting to a list, we obtain a snapshot of the data, allowing for immediate manipulation and analysis.

    Another scenario where this conversion becomes necessary is when integrating with libraries and frameworks that operate on traditional list-based data structures . Ensuring compatibility and seamless integration is vital, and converting IAsyncEnumerable<T> to List<T> facilitates this process.

    With a clear understanding of the necessity for conversion, we can now explore how to achieve this conversion.

    Using ToListAsync() Method to Convert IAsyncEnumerable

    Let’s start with a method that simulates fetching users in batches, mimicking data arriving asynchronously from a real-world database. By yielding each user individually using yield return , it adheres to the IAsyncEnumerable<T> pattern, allowing us to efficiently process data as it becomes available:

    static async IAsyncEnumerable<User> GetUsersAsync(int delayMilliseconds = 500)
        for (int page = 1; page <= 3; page++)
            await Task.Delay(delayMilliseconds);
            var users = new List<User>
                new User((page - 1) * 3 + 1, "Alice"),
                new User((page - 1) * 3 + 2, "Bob"),
                new User((page - 1) * 3 + 3, "John")
            foreach (var user in users)
                yield return user;
    

    When it comes to converting IAsyncEnumerable<T> to List<T>, the built-in ToListAsync() method from the System.Linq.Async NuGet package offers a powerful and suitable option. It’s also worth noting that this method is different from the EntityFrameworkQueryableExtensions ToListAsync(IQueryable<T>) method.

    Let’s see how to use it to convert our sample GetUserAsync() method:

    static async Task<List<User>> GetUsersAsListAsync(int delayMilliseconds = 500)
        var usersAsync = GetUsersAsync(delayMilliseconds);
        return await usersAsync.ToListAsync();
    

    Here, we can see that the conversion process is incredibly concise. By invoking ToListAsync() on an IAsyncEnumerable<T> instance and awaiting the result, we obtain a readily available List<T>.

    To validate the output and confirm that it indeed returns a List<T>, we can utilize the built-in GetType() method:

    var usersAsync = GetUsersAsync();
    var usersList = await usersAsync.ToListAsync();
    Console.WriteLine(usersList.GetType());

    Using GetType(), we retrieve the underlying type of our userList variable and then write it to the console:

    System.Collections.Generic.List`1[ConvertIAsyncEnumerableToListLibrary.Model.User]

    Our output indicates that the conversion has resulted in a List<T> collection, as expected.

    Using ToListAsync() Method With Cancellation Token for Conversion

    While the ToListAsync() method is simple and convenient for conversion, it is important to be aware of its possible drawbacks, particularly when dealing with potentially long-running asynchronous operations.

    How conversion using this method works is that it buffers the entire dataset into memory before returning the List<T>. When working with huge datasets, this can result in memory exhaustion or performance bottlenecks, especially if the procedure takes longer than expected.

    This is where the need to use a cancellation token comes in, acting as a sort of safeguard for our asynchronous operations. By providing a CancellationToken to the ToListAsync() method, we can cancel the data retrieval and processing if necessary.

    To use the cancellation token in our method, we first have to modify our IAsyncEnumerable method GetUsersAsync() to respect the provided token. This is a great practice that ensures the operation can be canceled efficiently at any point during its execution:

    static async IAsyncEnumerable<User> GetUsersAsync
    (int delayMilliseconds = 500, [EnumeratorCancellation] CancellationToken cancellationToken = default)
        for (int page = 1; page <= 3; page++)
            await Task.Delay(delayMilliseconds, cancellationToken);
            var users = new List<User>
                new User((page - 1) * 3 + 1, "Alice"),
                new User((page - 1) * 3 + 2, "Bob"),
                new User((page - 1) * 3 + 3, "John")
            foreach (var user in users)
                cancellationToken.ThrowIfCancellationRequested();
                yield return user;
    

    In this modified version, we pass the CancellationToken to Task.Delay to allow the delay to be cancelable. Additionally, we call cancellationToken.ThrowIfCancellationRequested() before yielding each user, to ensure that the operation can be canceled at any point.

    With the CancellationToken now integrated into our GetUsersAsync() method, we also need to adjust the GetUsersAsListAsync() method to support cancellation:

    Liked it? Take a second to support Code Maze on Patreon and get the ad free reading experience!
    Become a patron at Patreon!

    Leave a reply Cancel reply

    Your email address will not be published. Required fields are marked *