繁体   English   中英

C#StreamReader在try / finally中

[英]C# StreamReader in a try/finally

我今天有一个涉及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在最后关闭吗?

最简单的方法是使用using语句:

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

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

如果你需要明确地拼出finally ,你的第二个例子将起作用,除了你需要强制tr进行初始化:

TextReader tr = null;

当然,如果在执行tr = new StreamReader(...)之前发生异常,您当然希望在finally块中检查tr != null

是的,要么:

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-block中声明的,这使得finally块无法访问。

你的问题中的第二段代码没有编译的原因是tr变量没有给出一个值,如果new XmlSerializer要抛出异常,它也不会在try-block中得到一个,这意味着当变量到达finally块时,你有一个未定义的值。

如果你想绝对保持try / finally结构,那么解决方案是确保变量具有初始值,并且只有在它已经改变时才调用.Close

当然,最正确的方法是使用一个using块,它会为您处理所有细节。 请注意,这将改变阅读器和序列化程序对象之间的构造顺序,或者您可以使用这样的代码,这样可以保留您在问题中的顺序(在这种情况下,这并不重要):

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

关于此代码的评论

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 ,你最终会在finally块内部出现异常!

最好捕获System.IO.IOException这样你就可以正确处理这种情况,而不是用文件输入/输出处理掩盖问题......

不要在这里使用try / finally,使用Using语句,它与您使用更清晰的语法执行的操作完全相同。 答案是“是”,顺便说一下:)

你应该使用using关键字。

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

调用Dispose()方法时,对象超出块结尾的范围。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM