Skip to content

Convert/deconstruct in async-foreach only if TryGetNext succeeded #30258

@jcouv

Description

@jcouv

Should also cover nested deconstruction (with Deconstruct and with tuples).

        [Fact]
        public void TestWithExplicitlyConvertibleElementType()
        {
            string source = @"
using static System.Console;
using System.Threading.Tasks;
class C
{
    public static async System.Threading.Tasks.Task Main()
    {
        foreach await (Element i in new C())
        {
            Write($""Got({i}) "");
        }
    }
    public AsyncEnumerator GetAsyncEnumerator()
    {
        return new AsyncEnumerator();
    }
    public sealed class AsyncEnumerator : System.IAsyncDisposable
    {
        int i = 0;
        public int TryGetNext(out bool found)
        {
            Write($""Next({i}) "");
            found = i % 10 % 3 != 0;
            return found ? i++ : 0;
        }
        public async Task<bool> WaitForNextAsync()
        {
            Write($""NextAsync({i}) "");
            i = i + 11;
            bool more = await Task.FromResult(i < 30);
            return more;
        }
        public async ValueTask DisposeAsync()
        {
            Write($""Dispose({i}) "");
            await Task.Delay(10);
        }
    }
}
class Element
{
    int i;
    public static explicit operator Element(int value) { Write($""Convert({value}) ""); return new Element(value); }
    private Element(int value) { i = value; }
    public override string ToString() => i.ToString();
}";
            var comp = CreateCompilationWithTasksExtensions(source + s_interfaces, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics( );
            // PROTOTYPE(async-streams) Convert(0) is here because we're converting the result even if TryGetNext returned false
            CompileAndVerify(comp, expectedOutput: "NextAsync(0) Next(11) Convert(11) Got(11) Next(12) Convert(12) Got(12) " +
                "Next(13) Convert(0) NextAsync(13) Next(24) Convert(24) Got(24) Next(25) Convert(25) Got(25) " +
                "Next(26) Convert(0) NextAsync(26) Dispose(37)", verify: Verification.Skipped);
        }

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions