C#StreamReader在try/finally中

JL.*_*JL. 12 .net c#

我今天有一个涉及StreamReader类的问题.具体使用filename参数初始化此类,例如:

TextReader tr = new StreamReader(fileName);
Run Code Online (Sandbox Code Playgroud)

显然,当这个动作完成时,关闭流的重要性如下:

 tr.Close();
Run Code Online (Sandbox Code Playgroud)

我想在尝试/最后得到这个,问题是我找不到办法做到这一点.以下是我发现的一些不适用的变化:

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

更糟糕的是:

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

那么有可能让StreamReader在最后关闭吗?

ito*_*son 25

最简单的方法是使用一个using声明:

using (TextReader tr = new StreamReader(fileName))
{
  // ...
}
Run Code Online (Sandbox Code Playgroud)

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

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

TextReader tr = null;
Run Code Online (Sandbox Code Playgroud)

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


ang*_*son 8

是的,要么:

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

要不就:

using (TextReader tr = new StreamReader(fileName))
{
    var serializer = new XmlSerializer(type);
    var obj = serializer.Deserialize(tr);
}
Run Code Online (Sandbox Code Playgroud)

你的问题中第一段代码没有编译的原因是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);
}
Run Code Online (Sandbox Code Playgroud)