Extravaganza using ConfigureAwait, await and await foreach
As I was writing previous post I got some idea to “nest” await
s in the using
definition and make it little bit confusing.
Sadly, it didn’t get much confusing, because C# is generally well designed language. This was my try.
class Test : IAsyncDisposable
{
public ValueTask DisposeAsync() => throw new NotImplementedException();
public static Task<Test> CreateAsync() => throw new NotImplementedException();
public async Task Foo()
{
await using (var x = await CreateAsync())
{ }
}
}
Interesting combination? Sure. Yet still clear what it does. Trying to put ConfigureAwait
forces me to extract one await
call outside, as I showed in previous post, thus not much luck here.
public async Task Foo()
{
var t = await CreateAsync().ConfigureAwait(false);
await using (var x = t.ConfigureAwait(false))
{ }
}
But I’m not giving up. I can maybe abuse await foreach
, another new C# 8 feature, similar to await using
. With that I can abuse the IAsyncAnumerable<T>
and wrap it into the Task<T>
(and obviously that’s weird thing to do).
class Test
{
public IAsyncEnumerable<Test> Get() => throw new NotImplementedException();
public Task<IAsyncEnumerable<Test>> Get2() => throw new NotImplementedException();
public async Task Foo()
{
await foreach (var item in Get().ConfigureAwait(false))
{
}
}
public async Task Foo2()
{
await foreach (var item in (await Get2().ConfigureAwait(false)).ConfigureAwait(false))
{
}
}
}
The Foo
method is regular ConfigureAwait
usage like I described in previous post. But the Foo2
is more odd – which is what I wanted -, because thanks to ConfiguredCancelableAsyncEnumerable<T>
I can write it in “one line”.
I should surely rather go back to work. Although as I’m finishing this post, I’ll leave with something I rather not expand further… 😃
class Test : IAsyncDisposable
{
public async Task Foo()
{
await using (var x = ConfigureAwait(false).ConfigureAwait(false).ConfigureAwait(false).ConfigureAwait(false).ConfigureAwait(false).ConfigureAwait(false))
{ }
}
public Test ConfigureAwait(bool continueOnCapturedContext) => this;
public ValueTask DisposeAsync() => throw new NotImplementedException();
}