Consider the following code taken from the the Microsoft docs:
using FileStream createStream = File.Create(fileName);
// ...write to stream etc..
await createStream.DisposeAsync(); // <- isn't this done automatically because of the using clause in the first line`?
Isn't calling the DisposeAsync()
method superfluous?
CodePudding user response:
using
clause will call Dispose()
method, not DisposeAsync()
. It's not the same since Dispose()
is blocking call and the presence of DisposeAsync
suggests that dispose might be resource intensive and so you don't want to call Dispose
if you can instead call DisposeAsync
.
The code as written will first call DisposeAsync
and then at the end of the scope it will also call Dispose
. We can assume it's harmless because implementing class should have a check that resource was already disposed so second Dispose
should do nothing. However, if you use C#8 , you can use await using
:
await using FileStream createStream = File.Create(fileName);
This is the same as using
but it will call await DisposeAsync()
at the end of the scope, instead of Dispose
. So just like you do now, but automatically (and in finally block). It works with IAsyncDisposable
target (such as FileStream
which inherits from Stream
which implements IAsyncDisposable
).
CodePudding user response:
You need to check the whole snippet here:
public static async Task Main()
{
var weatherForecast = new WeatherForecast
{
// ...
};
string fileName = "WeatherForecast.json";
using FileStream createStream = File.Create(fileName);
await JsonSerializer.SerializeAsync(createStream, weatherForecast);
await createStream.DisposeAsync();
Console.WriteLine(File.ReadAllText(fileName));
}
using
declaration will call Dispose
in generated finally block at the end of the current scope, the problem here is that the file is accessed before the end of the scope:
Console.WriteLine(File.ReadAllText(fileName));
So the await createStream.DisposeAsync();
is actually needed otherwise the file will not be accessible (or even if it would be - potentially not all data will be flushed).
In this concrete case switching to using
statement (the one with braces, also both using
statement and declaration actually support handling IAsyncDisposable
) would be cleaner and will make await createStream.DisposeAsync();
call redundant:
await using (FileStream createStream = File.Create(fileName))
{
await JsonSerializer.SerializeAsync(createStream, weatherForecast);
}
Console.WriteLine(File.ReadAllText(fileName));