I need to define methods in my core interface that return lists. My project heavily relies on the use of async/await so I need to define my core references/interfaces as asynchronous as possible. I also use EF7 for my data-access layer. I currently use IAsyncEnumerable
everywhere.
I am currently deciding whether to keep using IAsyncEnumerable
or to revert back to using Task<IEnumerable<T>>
. IAsyncEnumerable
seems promising at this point. EF7 is using it as well. The trouble is, I don't know and can't figure out how to use it. There is almost nothing on the website that tells anyone how to use Ix.Net. There's a ToAsyncEnumerable
extension that I can use on IEnumerable
objects but this wouldn't do anything asynchronously (or does it??). Another drawback is that given the below signature:
IAsyncEnumerable GetPersons();
Because this isn't a function that returns Task, I can't use async/await inside the function block.
On the other hand, my gut is telling me that I should stick with using Task<IEnumerable<T>>
. This of course has it's problems as well. EF does not have an extension method that returns this type. It has a ToArrayAsync
and ToListAsync
extension method but this of course requires you to call await inside the method because Task<T>
isn't covariant. This potentially is a problem because this creates an extra operation which could be avoided if I simply return the Task
object.
My questions is: Should I keep using IAsyncEnumerable
(preferred) or should I change everything back to Task<IEnumerable<T>>
(not preferred)? I'm open to other suggestions as well.
I would go with IAsyncEnumerable
. It allows you to keep your operations both asynchronous and lazy.
Without it you need to return Task<IEnumerble>
which means you're loading all the results into memory. This in many cases meaning querying and holding more memory than needed.
The classic case is having a query that the user calls Any
on. If it's Task<IEnumerable>
it will load all the results into memory first, and if it's IAsyncEnumerable
loading one result will be enough.
Also relevant is that with Task<IEnumerable>
you need to hold the entire result set in memory at the same time while with IAsyncEnumerable
you can "stream" the results a few at a time.
Also, that's the direction the ecosystem is heading. It was added by reactive extension, by a new library suggested by Stephen Toub just this week and will probably be supported in the next version of C# natively.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With