I am using StreamReader
as shown below in my code:
string json = await new StreamReader(context.Request.Body).ReadToEndAsync();
// ... use json variable here in some other code
And I stumbled upon using
statement. Is there any difference between my first statement vs using the using
statement with StreamReader
?
Should I be using using
statement with StreamReader
here in prod code?
string json;
using (var reader = new StreamReader(context.Request.Body))
{
json = await reader.ReadToEndAsync();
}
Is there any difference between my first statement vs using the using statement with StreamReader
Yes. The difference is that when you wrap StreamReader
in a using
statement it will clear up some resources directly instead of waiting for the garbage collector. More specifically it will call Dispose()
on StreamReader
. You should almost always use using
when the class implements IDisposable
.
If your app simply uses an object that implements the IDisposable interface, you should call the object's IDisposable.Dispose implementation when you are finished using it.
Thanks to .NET Core being open source we can take a look at the source for StreamReader
:
protected override void Dispose(bool disposing)
{
if (m_stream != null)
{
if (disposing)
{
m_stream.Close();
}
m_stream = null;
m_buffer = null;
m_curBufPos = 0;
m_curBufLen = 0;
}
m_disposed = true;
}
As you can see it calls Close()
on the stream, which (according to the docs) in turn will call Dispose()
on the stream itself.
Correctly disposing objects can be crucial when working with larger objects or streams. However, I will try to target your other question.
Should I be using using statement with StreamReader here in prod code?
Yes, no and maybe. In your partical case you have a context.Request.Body
as a Stream
(which I assume is from HttpContext
). There is no need for the StreamReader
to close that particular stream. It will be disposed correctly (later) anyway. Also, there might be some other resource that need access to that particual stream later in the pipeline.
Generally, if the class implements IDisposable
then you should wrap it in a using
. But here I think that you have two better choices:
1.
If you actually have a json (as your variable suggest), you can deserialize it directly using JsonSerializer
found in System.Text.Json.JsonSerializer
:
YourModel model = await System.Text.Json.JsonSerializer.DeserializeAsync<YourModel>(context.Request.Body);
UPDATE: Or if you are using .NET 5 you have access to HttpResponseJsonExtensions and can use ReadFromJsonAsync
. Then you can simply try the following:
YourModel model = await context.Request.ReadFromJsonAsync<YourModel>();
Thanks to caius-jard.
2.
Use the overload of StreamReader
that doesn't close the stream.
string json;
using (var reader = new StreamReader(stream, Encoding.UTF8, true, -1, true))
{
json = await reader.ReadToEndAsync();
}
So, to sum up. Yes, there is a difference when using using
. However, in your particular case you have better options.