实际上,我尝试了对代码进行防错,最终使其看起来非常混乱。
我有一个功能设置来读取某种类型的文件。我希望函数在出现问题时返回false,如果一切正常则返回true。我无法弄清楚如何构建一切。
我有一个尝试打开文件流的初始try-catch块。在那之后,我在读取过程中进行了一些其他检查,例如文件大小和某些偏移处的值。我设置的方式是使用if else语句。如:
if(condition){
}
else{
MessageBox.Show("There was an error");
br.Dispose();
fs.Dispose();
return false;
}
... br是二进制阅读器,fs是文件流。像这样有很多块,这么多次写同样的东西似乎是不好的做法。首先想到的是将整个事物包装在try-catch语句中并抛出异常而不是使用if else块。我记得在阅读try-catch语句时,拥有它们很好,但不能用它们包装所有内容。说实话,我仍然不完全理解为什么将所有内容包装在try catch语句中是不好的做法,因为它们只有在出现错误时才会生效,在这种情况下程序会向南移动无论如何...
另外,我是否必须关闭二进制阅读器和文件流,还是关闭另一个?有没有办法在不必处理它们的情况下使用它们?
答案 0 :(得分:5)
如何使用using
关键字?这包括你在try - finally块中使用IDisposable
;
bool success = true;
using(var fs = new FileStream(fileName, FileMode.Create)))
using(var br = new BinaryReader(fs))
{
// do something
success = result;
}
return success;
嵌套使用块将确保始终正确关闭和处理文件流和二进制阅读器。
您可以阅读more about using in MSDN。它使得IDisposable
的使用更加简洁,无需明确的激活处理。
关于你的陈述:
我记得在阅读关于try-catch语句的时候,这很好 拥有它们,但不要用它们包装所有东西。
我总是使用简单的规则,如果我无法处理并从特定代码块中的异常中恢复,请不要尝试捕获它。允许异常将堆栈'冒泡'到一个更有意义的方法来捕获它。使用这种方法,您会发现您不需要添加许多try-catch块,您将倾向于在与服务集成时使用它们(例如文件系统,网络等...),但您的业务逻辑几乎总是如此没有异常处理机制。
答案 1 :(得分:1)
只需将using
关键字用于您的一次性对象即可。在using
关键字的区块内,您可以throw
例外或return
,而无需担心处置;它将自动发生在您身上。
try-catch
块不是一个好主意,只是因为存在一个更好的选择:try-finally
块。但是using
关键字更好,因为它基本上扩展为try-finally
块,它负责处理对象。
关闭文件流也将关闭二进制阅读器,因此将处理它们。为什么要在不处理它们的情况下使用它们?处置它们会更好,通过using
处理它们是最好的办法。
答案 2 :(得分:0)
我认为确保文件流处理的最佳方法是使用以下using
块来包装它们
using (FileStream)
{
....
}
答案 3 :(得分:0)
是的,这是不好的做法。
您应该抛出异常,而不是返回指示问题是否发生的布尔值。例如:
if (headNotValid)
throw new Exception("Header was not valid");
在某些情况下,最好建立一个新的异常类。
使用继承自IDisposable
的类时,应使用using
指令。
using (var stream = new FileStream(filename))
{
}
即使在using
块中抛出异常,也可以保证您的流被处理掉。
总之,我更喜欢这样的事情:
private void string ParseFile(string filename)
{
using (var stream = new FileStream(filename))
{
if (somethingNotValid)
throw new Exception(...);
return ...;
}
}
在你的主要:
{
try
{
var value = ParseFile(filename);
}
catch (Exception)
{
Console.WriteLine(..);
}
}
答案 4 :(得分:0)
使用using
关键字。使用using
,您可以重写这样的内容:
public static int CountCars()
{
SqlConnection conn = new SqlConnection(connectionString);
try
{
SqlCommand cmd = conn.CreateCommand();
conn.Open();
try
{
cmd.CommandText = "SELECT COUNT(1) FROM Carsd";
return (int)cmd.ExecuteScalar();
}
finally
{
if(cmd != null)
cmd.Dispose();
}
}
finally
{
if(cmd != null)
conn.Dispose();
}
}
进入这个:
public static int CountCars()
{
using(SqlConnection conn = new SqlConnection(connectionString))
using(SqlCommand cmd = conn.CreateCommand())
{
conn.Open();
cmd.CommandText = "SELECT COUNT(1) FROM Carsd";
return (int)cmd.ExecuteScalar();
}
}
两个代码片段在编译时将生成完全相同的IL代码。这些示例来自http://coding.abel.nu/2011/12/idisposable-and-using-in-c/,其中我写了一些有关使用和IDisposable
的详细信息。