【问题标题】:Any issue with nesting "using" statements in c#?在 C# 中嵌套“使用”语句有什么问题吗?
【发布时间】:2014-04-14 21:37:53
【问题描述】:

我最近下载了 Visual Studio 2013,并对我正在处理的项目运行了代码分析。它引发了我正在解决的几个问题,但特别是关于我如何使用“使用”IDisposable 语句。

这是我的代码示例:

using (MemoryStream msDecrypt = new MemoryStream(encryptedText.ToBase64Byte()))
{
    using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
    {
        using (StreamReader srDecrypt = new StreamReader(csDecrypt))
        {
            return srDecrypt.ReadToEnd();
        }
    }
}

我了解分析警告试图告诉我以这种方式处置多个对象可能会引发对象处置问题。

我确信在上述情况下对一个对象进行处理不会引发异常。那么我应该修改我的代码还是保持原样?

【问题讨论】:

  • 这种做法迄今为止对我来说从未失败过,所以我认为它非常好。
  • 感谢大家的反馈。我确信我对 using 语句的实现很好,但是当分析工具向我突出显示它时,我开始怀疑自己。我会将第一个答案标记为正确,但所有答案都非常有效!谢谢!
  • 您也可以在一个using 语句中包含所有这些,变量类型设置为Stream,唯一的问题是您必须在块内强制转换为ReadToEnd展示。它确实删除了警告。见this question
  • 也就是说,忽略警告,您不必添加不必要的模糊性来避免误报代码分析警告。
  • 其中一些流将被多次释放,因为StreamReader 拥有并释放关联的流。

标签: c# idisposable using


【解决方案1】:

据我所知,您的代码应该没有问题,我过去一直使用嵌套的 using 语句。

通过查看other questions,我认为问题出在代码分析工具本身以及 CA2000 和 CA2202 规则上。在 using 语句中使用各种流和读取器类型时,经常会出现误报。

您应该忽略警告并继续,因为替代方法(例如 try/finally)会产生错误代码并且您的代码是有效的。

【讨论】:

    【解决方案2】:

    原因来自MSDN

    嵌套 using 语句(在 Visual Basic 中使用)可能导致违规 CA2202 警告。如果嵌套内部的 IDisposable 资源 using 语句包含外部 using 语句的资源, 嵌套资源的 Dispose 方法释放所包含的 资源。当出现这种情况时,外部的 Dispose 方法 using 语句尝试第二次释放其资源。

    在你的情况下。像这样使用它很好。所以,你应该压制警告。

    你可以通过实现 Try/finally 来修改你的代码来抑制警告的丑陋方式。不过,您确实应该避免这种情况。

    【讨论】:

      【解决方案3】:

      我没有看到关于使用多个 using 语句来处置对象的任何问题。 嵌套 using 语句很常见,并且您的代码是有效的。

      使用不同类型的对象,如果想节省空间和提高可读性,可以使用单行语法嵌套:

      using (MemoryStream msDecrypt = new MemoryStream(encryptedText.ToBase64Byte()))
      using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
      using (StreamReader srDecrypt = new StreamReader(csDecrypt))
      {
           return srDecrypt.ReadToEnd();
      }
      

      您遇到的问题是使用代码分析反复出现的(您可以找到警告here 的原因)。然后,您可以忽略有关多个 using 语句的警告,因为这是误报,并且您的代码正常且有效。

      您也可以通过这种方式抑制警告(感谢@Jordão),如this nice answer 中所述:

      [SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times")]
      public void MyMethodWithUsings()
      {
           using (MemoryStream msDecrypt = new MemoryStream(encryptedText.ToBase64Byte()))
           using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
           using (StreamReader srDecrypt = new StreamReader(csDecrypt))
           {
                 return srDecrypt.ReadToEnd();
           }
      }
      

      如果要删除警告,则必须使用块 try/finally 重写代码并在 finally 块中调用对象的 Dispose() 方法,但这会产生糟糕且不容易的结果阅读代码,您可以在this question 中看到。

      【讨论】:

        【解决方案4】:

        这是代码分析以及 CA2000 和 CA2202 经常出现的问题。

        您可以通过不使用using 而是使用try/finally/dipose 来修复这些警告。不推荐这样做,因为它会产生糟糕的代码。

        您的代码可以正常工作,只需取消这些警告

        另请参阅 https://stackoverflow.com/a/21849534/870604 以了解 StreamReader/Writer 和底层流所有权。

        【讨论】:

          【解决方案5】:

          对于这种类型的警告,您可以很容易地忽略该警告,因为它通常是误报。查看以下链接了解更多信息:

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2022-12-12
            • 1970-01-01
            • 2012-01-11
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多