Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Async-streams: allow pattern-based await foreach to use extension methods #32289

Open
jcouv opened this issue Jan 9, 2019 · 1 comment
Open
Assignees
Milestone

Comments

@jcouv
Copy link
Member

jcouv commented Jan 9, 2019

Previously, we thought this would be handled by the general feature of allowing pattern-based foreach to use extension methods. But that was split into a separate feature (hopefully still candidate for 8.0).

Even if we don't do it for regular foreach, LDM wants to do this for await foreach.
And when we do it, the order should be: (1) instance method, (2) interface, (3) extension method.
That order matches the behavior we want for foreach and we also think it is sensible in general.

From LDM 1/9.

        [Fact]
        public void TestGetAsyncEnumeratorPatternViaExtensions()
        {
            string source = @"
public class C
{
    async System.Threading.Tasks.Task M()
    {
        await foreach (var i in new C())
        {
        }
    }
    public sealed class Enumerator
    {
    }
}
public static class Extensions
{
    public static C.Enumerator GetAsyncEnumerator(this C c)
    {
        throw null;
    }
}";
            var comp = CreateCompilationWithMscorlib46(source);
            comp.VerifyDiagnostics(
                // (6,33): error CS8411: Async foreach statement cannot operate on variables of type 'C' because 'C' does not contain a public definition for 'GetAsyncEnumerator'
                //         await foreach (var i in new C())
                Diagnostic(ErrorCode.ERR_AwaitForEachMissingMember, "new C()").WithArguments("C", "GetAsyncEnumerator").WithLocation(6, 33)
                );
        }
@divega
Copy link

divega commented Sep 27, 2019

If this was implemented it would allow EF Core to define an extension method in our main namespace that would enable our IQuerayble<T> based queries to be directly consumed with await foreach:

var orders = 
    from o in context.Orders.Include(o => o.Lines)
    where o.Status == OrderStatus.Pending
    select o;

await foreach(var o in orders)
{
    Process(o);
}

Currently we define AsAsyncEnumerable<T>() so our customers can do it like this:

var orders = 
    from o in context.Orders.Include(o => o.Lines)
    where o.Status == OrderStatus.Pending
    select o;

await foreach(var o in orders.AsAsyncEnumerable())
{
    Process(o);
}

cc @smitpatel, @bricelam

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants