代码之家  ›  专栏  ›  技术社区  ›  JL. Hans Passant

C#try/finally中的StreamReader

  •  11
  • JL. Hans Passant  · 技术社区  · 14 年前

    今天我有一个关于StreamReader课程的问题。特别是使用filename参数初始化此类,例如:

    TextReader tr = new StreamReader(fileName);
    

    显然,当此操作完成时,关闭流很重要,如下所示:

     tr.Close();
    

        try
            {
                var serializer = new XmlSerializer(type);
                TextReader tr = new StreamReader(fileName);
                var obj = serializer.Deserialize(tr);
            }
        finally
            {
                tr.Close();    
            }
    

    更糟糕的是:

         TextReader tr;  
            try
            {
                var serializer = new XmlSerializer(type);
                tr = new StreamReader(fileName);
                var obj = serializer.Deserialize(tr);
            }
            finally
            {
                tr.Close();    
            }
    

    那么,是否有可能在最终阶段关闭StreamReader?

    5 回复  |  直到 14 年前
        1
  •  26
  •   itowlson    14 年前

    最简单的方法是使用 using

    using (TextReader tr = new StreamReader(fileName))
    {
      // ...
    }
    

    编译器将为您生成一个try-finally块,并在finally中放置要调用Close(实际上是Dispose)的代码。

    如果你需要详细说明 finally 显然,您的第二个示例将起作用,但您需要强制 tr 草签:

    TextReader tr = null;
    

    你当然会想检查一下 tr != null 在finally块中,以防之前发生异常 tr = new StreamReader(...) 他被处决了。

        2
  •  8
  •   Lasse V. Karlsen    14 年前

    是的,或者:

    TextReader tr = null;
    try
    {
        var serializer = new XmlSerializer(type);
        tr = new StreamReader(fileName);
        var obj = serializer.Deserialize(tr);
    }
    finally
    {
        if (tr != null)
            tr.Close();    
    }
    

    或者只是:

    using (TextReader tr = new StreamReader(fileName))
    {
        var serializer = new XmlSerializer(type);
        var obj = serializer.Deserialize(tr);
    }
    

    tr 变量是在try块内声明的,这使得finally块无法访问它。

    变量未给定值,如果 new XmlSerializer 如果抛出异常,它也不会在try块中得到异常,这意味着当变量到达finally块时,变量中可能有一个未定义的值。

    .Close

    当然,最正确的方法是使用 using 块,它为您处理所有细节。请注意,这将更改读取器和序列化器对象之间的构造顺序,或者您可以使用类似的代码,这将保留您在问题中的顺序(但在本例中这并不重要):

    var serializer = new XmlSerializer(type);
    using (TextReader tr = new StreamReader(fileName))
    {
        var obj = serializer.Deserialize(tr);
    }
    
        3
  •  3
  •   t0mm13b    8 年前

    关于此代码的注释

    TextReader tr;  
            try
            {
                var serializer = new XmlSerializer(type);
                tr = new StreamReader(fileName);
                var obj = serializer.Deserialize(tr);
            }
            finally
            {
                //tr.Close(); 
                // Correct way
                if (tr != null) tr.Close();
            }
    

    StreamReader 如果失败,那么 finally 块被执行,现在,在这里, tr null 作为失败的结果,您将在 最后

    最好赶上火车 System.IO.IOException 这样您就可以正确地处理这种情况,而不是用文件输入/输出处理来掩盖问题。。。

        4
  •  2
  •   Ana Betts    14 年前

        5
  •  2
  •   tster    14 年前

    你应该使用 using 关键词。

    using (TextReader tr = new StreamReader(fileName))
    {
        var obj = serializer.Deserialize(tr);
    }