IAsyncEnumerable in .NET C# 8.03 min read

OOOOPS…I DID IT AGAIN!?

I want to apologize for not respecting and failing my deadlines, with writing a new post every two weeks. I received a bunch of e-mails from you guys asking me when will my next post be published.
So I feel responsible to point out to you that I’m currently very, very busy working on a bunch of projects. I am also preparing some cool new digital content for you which is going to enhance the overall learning experience of a vast .NET world.

I also want to seize this opportunity and say big THANK YOU for supporting me and giving me the reason to publish more and more content.

Now let’s dive into today’s topic.

In my previous post, I wrote about collections in C#. It was an intro to today’s post, as I stumbled upon some cool new feature inside C# 8.0.

Maybe some of you are already aware of this new cool feature, but I guess most of the people are not.

WHAT’S THAT?

It’s the new addition to C# 8.0 which is also called *async streams* (more about it at https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-8.0/async-streams?WT.mc_id=devto-blog-antchu). If you are not aware of this, let’s dive a little deeper of what it does and why it’s useful.

IN SHORT

It is intended to replace Task<IEnumerable>.

WHY?

To retrieve data asynchronously from our DB or API and stream those results back as they become available.

SHOW ME THE CODE!

If it’s still unclear what it does, it’s okay! We will take a look at an example.
Let’s imagine we are building some DAL and need to create a function which queries data or some kind of API. Probably you will end up with using Task<IEnumerable<T>> and create something like this:

public async Task<IEnumerable<Project>> GetAllProjects()

And in GetAllProjects() method you will probably have something like this:

public async Task<IEnumerable<Project>> GetAllProjects()
{
    ...
    var iterator = ...;
    var projects = new List<Project>();
    while (iterator.HasMoreResults)
    {
        foreach (var project in await iterator.ReadNextAsync())
        {
            projects.Add(project);
        }
    }
    return projects
}

Using this way our code will work but it will work inefficiently!
Just imagine working with a large amount of data.

Hint: Sloooooow…

If you are about to tweak this a little bit, you are probably going to end up with returning IEnumerable< Task<IEnumerable<Project>>>.

But this is a counterintuitive way because it’s not obvious how do we invoke this method and work with resulting data.

Oh, now what!?

You are probably thinking on how to bypass all this fuss and you came up with this, great, great idea!!!

AHAAA moment!

Iterator has a ReadNextAsync method, let’s use it Luke!!

public IEnumerable<Project> GetAllProjects()
{
    ...
    while (iterator.HasMoreResults)
    {
        foreach (var project in iterator.ReadNextAsync().Result)
        {
            yield return project;
        }
    }
}

Again, if you are about to solve the issue by using above mentioned code, think twice! Don’t go that way. You will eventually end up blocking your code.

IAsyncEnumerable<T>

So here is where the new feature really shines up!

We create our method like this:

public async IAsyncEnumerable<Project> GetAllProjects()
{
    ...
    while (iterator.HasMoreResults)
    {
        foreach (var project in await iterator.ReadNextAsync())
        {
            yield return project;
        }
    }
}

And we consume it like this:

await foreach (var project in projectRepo.GetAllProjects())
{
	// do whatever you want with "project" object...
}

CONCLUSION

As you can see, this new feature gives us much cleaner and efficient code.
So please use it as it’s really,really,really great feature.

Thanks for reading and stay tuned for some more cool content to come!

Leave a Reply

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