Resharper suggests to improve using statements with await key word to single line await using statements. As an example, the following code snippet :
private async Task<string> ReadResponseAsync(HttpContext context)
{
var originalBody = context.Response.Body;
try
{
using (var responseStream = new MemoryStream())
{
context.Response.Body = responseStream;
await _next(context).ConfigureAwait(false);
var response = context.Response;
response.Body.Seek(0, SeekOrigin.Begin);
using (var responseReader = new StreamReader(response.Body))
{
var responseContent = await responseReader
.ReadToEndAsync()
.ConfigureAwait(false);
response.Body.Seek(0, SeekOrigin.Begin);
await responseStream.CopyToAsync(originalBody)
.ConfigureAwait(false);
return responseContent;
}
}
}
finally
{
context.Response.Body = originalBody;
}
}
after applying successive Resharper suggestions the code becomes the following :
private async Task<string> ReadResponseAsync(HttpContext context)
{
var originalBody = context.Response.Body;
try
{
await using var responseStream = new MemoryStream();
context.Response.Body = responseStream;
await _next(context).ConfigureAwait(false);
var response = context.Response;
response.Body.Seek(0, SeekOrigin.Begin);
using var responseReader = new StreamReader(response.Body);
var responseContent = await responseReader
.ReadToEndAsync()
.ConfigureAwait(false);
response.Body.Seek(0, SeekOrigin.Begin);
await responseStream.CopyToAsync(originalBody)
.ConfigureAwait(false);
return responseContent;
}
finally
{
context.Response.Body = originalBody;
}
}
Are these two code snippets similar ? What is actually being improved here ? I am not understanding this feature of C# for using statements.
Two things changed when you accepted that recommendation:
await using
, which you can use on types that implement the new IAsyncDisposable
. It's the same as the regular using
, except it calls DisposeAsync()
instead of Dispose()
.
The change from a using
block, to just a statement. This recommendation is just to minimize nesting in your code. Once the object falls out of scope, then Dispose()
/DisposeAsync()
is called. You can read more about it in the documentation.
Those are two separate features that you can use independently of each other (you can use await using
with a block, or use using
as a statement), but both are brand new in the language.