【问题标题】:StreamReader with using statement difference?StreamReader 与 using 语句的区别?
【发布时间】:2021-09-06 03:57:27
【问题描述】:

我在我的代码中使用StreamReader,如下所示:

string json = await new StreamReader(context.Request.Body).ReadToEndAsync();
// ... use json variable here in some other code

我偶然发现了using 声明。我的第一个语句与使用using 语句和StreamReader 之间有什么区别吗?

我应该在产品代码中使用using 语句和StreamReader 吗?

        string json;
        using (var reader = new StreamReader(context.Request.Body))
        {
            json = await reader.ReadToEndAsync();
        }

【问题讨论】:

  • 对于您的特殊情况,context.Request.Body 将被处置,无论其是否由框架拥有和管理。流阅读器可以采用构造重载来保持流打开,尽管它在这里并不是很有用。此外,由于这可能是 json,因此还有其他方法可以实现这一点,即将流/主体直接传递给 json 反序列化器(等等)。
  • 有一种新的 using 语法可以减少分解/嵌套代码:using var reader = new StreamReader(...); var json = reader.Read...。看看吧
  • 你可以跳过所有这些低级字符串/阅读器的麻烦,让http请求为你解压你的json到一个类,见docs.microsoft.com/en-us/dotnet/api/…
  • 虽然我同意这是关于using 的问题。我确实认为这个问题专门询问如何使用HttpRequest 处理using,从而使其比建议的副本更具体。

标签: c# asp.net-core streamreader using


【解决方案1】:

我的第一个语句与使用 using 之间有什么区别吗 StreamReader 语句

是的。不同的是,当您将StreamReader 包装在using 语句中时,它将直接清除一些资源,而不是等待垃圾收集器。更具体地说,它将在StreamReader 上调用Dispose()。当类实现 IDisposable 时,您几乎应该总是使用 using。

如果您的应用只是使用实现 IDisposable 的对象 接口,你应该调用对象的 IDisposable.Dispose 使用完毕后执行。

由于 .NET Core 是开源的,我们可以查看 the source 以获取 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;
}

如您所见,它在流上调用 Close(),而 (according to the docs) 又会在流本身上调用 Dispose()。

正确处理对象可能在处理较大的对象或流时至关重要。不过,我会尝试针对您的其他问题。

我应该在产品代码中使用带有 StreamReader 的 using 语句吗?

是的,不,也许。在您的特定情况下,您有一个context.Request.Body 作为Stream(我假设来自HttpContext)。 StreamReader 无需关闭该特定 流。无论如何,它将被正确处理(稍后)。此外,可能还有一些其他资源需要稍后在管道中访问该特定流。

一般来说,如果类实现了IDisposable,那么您应该将它包装在using 中。但在这里我认为你有两个更好的选择:

1. 如果您实际上有一个 json(正如您的变量所建议的那样),您可以使用在 System.Text.Json.JsonSerializer 中找到的 JsonSerializer 直接反序列化它:

YourModel model = await System.Text.Json.JsonSerializer.DeserializeAsync<YourModel>(context.Request.Body);

更新: 或者,如果您使用的是 .NET 5,您可以访问 HttpResponseJsonExtensions 并且可以使用 ReadFromJsonAsync。然后您可以简单地尝试以下操作:

YourModel model = await context.Request.ReadFromJsonAsync<YourModel>();

感谢caius-jard。

2. 使用不会关闭流的overload ofStreamReader。

string json;
using (var reader = new StreamReader(stream, Encoding.UTF8, true, -1, true))
{
    json = await reader.ReadToEndAsync();
}

所以,总结一下。是的,使用using 时会有所不同。但是,在您的特定情况下,您有更好的选择。

【讨论】:

  • 也许会稍微考虑一下代表您提出请求 - docs.microsoft.com/en-us/dotnet/api/… - 比买狗并自己吠叫更好!
  • 谢谢!我实际上是在寻找这个,因为我知道我在某个地方使用过它。但是没找到。我会把它添加到我的答案中。
【解决方案2】:

查看此链接

https://www.c-sharpcorner.com/UploadFile/manas1/usage-and-importance-of-using-in-C-Sharp472/

简而言之:“using”语句确保托管/非托管资源对象正确释放,即使在 using 块中发生任何异常,您也不必显式调用“Dispose”方法

你也可以从微软官方网站进一步阅读

https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/using-statement#:~:text=The%20using%20statement%20calls%20the,t%20be%20modified%20or%20reassigned.

【讨论】:

    猜你喜欢
    • 2019-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-13
    • 1970-01-01
    • 2012-09-17
    • 1970-01-01
    相关资源
    最近更新 更多