[英]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.