【问题标题】:How to dispose File.OpenRead()如何处理 File.OpenRead()
【发布时间】:2011-07-24 15:34:03
【问题描述】:

如何正确处理 File.OpenRead()。我目前正在使用以下代码?

using (BinaryReader br = new BinaryReader(File.OpenRead(path)))
{
   myByte = br.ReadByte();
}

在分析代码时,我在 Visual Studio 中得到以下信息:

警告 1 CA2000: Microsoft.Reliability:方法中 'Program.Main(string[])', 对象 'File.OpenRead(path)' 未处理 沿着所有异常路径。称呼 System.IDisposable.Dispose 对象 'File.OpenRead(path)' 先于所有 对它的引用超出了范围。

【问题讨论】:

    标签: c# dispose


    【解决方案1】:

    怎么样:

    using (Filestream fs = File.OpenRead(Path))
    {
        using (BinaryReader br = new BinaryReader(fs))
        {
            myByte = br.ReadByte();
        }
    }
    

    【讨论】:

    • 简单,直接,一切都应该如此。为简洁起见,您甚至可以放弃所有外部括号(但这是主观的)。
    • 返回另一个警告:警告 1 CA2202:Microsoft.Usage:对象“fs”可以在方法“Program.Main(string[])”中多次处理。为避免生成 System.ObjectDisposedException,您不应在对象上多次调用 Dispose。: Lines: 24
    【解决方案2】:

    File.OpenRead 返回一个 FileStream,它也是 IDisposible。如果你愿意,你可以把它放在一个外部 using 块中,或者声明它并在你当前的 using 之外处理它。

    【讨论】:

      【解决方案3】:

      乍一看,这似乎是一个误报,因为处置BinaryReader也会处置File.OpenRead返回的FileStream

      发件人:http://msdn.microsoft.com/en-us/library/azy2k2bx.aspx

      当 disposing 参数为 true 时,此方法释放此 BinaryReader 引用的任何托管对象所持有的所有资源。该方法调用每个被引用对象的 Dispose 方法。

      但是,有一种极端情况,FileStream 确实没有被释放:当BinaryReader 的构造函数抛出异常时!

      解决方案:
      编写代码的正确方法是这样的:

      using (var fs = File.OpenRead(path))
      {
          BinaryReader br = new BinaryReader(fs);
          myByte = br.ReadByte();
      }
      

      背景:
      BinaryReader 仅包含对 FileStream 的引用,因此不需要处理。
      代码分析同意这一观点。


      顺便说一句:当将此解决方案用于可写流时,在释放流之前刷新写入器很重要:

      using (var fileStream = new FileStream(...))
      {
          var writer = new StreamWriter(fileStream);
      
          writer.WriteLine(...);
      
          writer.Flush(); // <-- Important
      }
      

      如果您忘记了这一点,您的流可能不包含使用 StreamWriter 写入的所有内容。

      【讨论】:

      • +1,好点。文档中的示例读起来就像问题中的代码:File.Open 的结果没有明确处理。
      • 是的,这也是我喜欢的想法。
      • 终于!微软似乎喜欢的一种方式!我之前一直在压制代码分析消息,但不禁感到……肮脏。
      【解决方案4】:

      File.OpenRead 创建的 FileStream 和您在该 FileStream 上创建的 BinaryReader 都需要处理,因此您需要明确引用每个文件:

      using(FileStream fs = File.OpenRead(path))
      using(BinaryReader br = new BinaryReader(fs))
      {
         myByte = br.ReadByte();
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-02-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-03-03
        • 1970-01-01
        相关资源
        最近更新 更多