简单的最佳实践问题。
你应该嵌套try catch语句还是只使用方法呢?
例如,如果您有一个打开文件,执行操作并关闭文件的方法,您应该将打开和关闭放在try catch外面,或者将关闭放在finally块中。
现在,如果打开文件的方法失败了,该方法会断言,对吧?那么,你应该将其包装在try catch块中呢,还是应该从另一个方法调用它,而该方法反过来具有try catch块呢?
简单的最佳实践问题。
你应该嵌套try catch语句还是只使用方法呢?
例如,如果您有一个打开文件,执行操作并关闭文件的方法,您应该将打开和关闭放在try catch外面,或者将关闭放在finally块中。
现在,如果打开文件的方法失败了,该方法会断言,对吧?那么,你应该将其包装在try catch块中呢,还是应该从另一个方法调用它,而该方法反过来具有try catch块呢?
在打开文件的方法中,我会使用using语句而不是try catch。using语句可以确保如果发生异常时Dispose方法被调用。
using (FileStream fs = new FileStream(file, FileMode.Open))
{
//do stuff
}
执行的操作与以下代码相同:
FileStream fs;
try
{
fs = new FileStream(file, FileMode.Open);
//do Stuff
}
finally
{
if(fs!=null)
fs.Dispose();
}
现在我们有了lambda表达式、类型推断和其他一些东西,这使得另外一些语言中常见的习惯用法在C#中也很有意义。你的例子是关于打开一个文件,对它进行一些操作,然后关闭它。现在,你可以编写一个帮助方法来打开文件,并且负责确保关闭/释放/清理文件,但是调用你提供的lambda表达式来执行“操作”部分。这将帮助您在一个地方正确地处理复杂的try/catch/finally dispose/cleanup事项,然后反复使用。
以下是示例:
public static void ProcessFile(string filePath, Action<File> fileProcessor)
{
File openFile = null;
try
{
openFile = File.Open(filePath); // I'm making this up ... point is you are acquiring a resource that needs to be cleaned up after.
fileProcessor(openFile);
}
finally
{
openFile.Close(); // Or dispose, or whatever.
}
}
现在,调用这个方法的人不必担心如何打开文件或关闭/释放它。他们可以像这样做:
Helpers.ProcessFile("C://somefile.txt", f =>
{
while(var text = f.ReadLine())
{
Console.WriteLine(text);
}
});
这是一个关于代码风格的问题,但对我来说,我尽量避免在单个方法中嵌套超过一层的try/catch/finally语句。当你遇到嵌套的try时,几乎肯定已经违反了“一个函数=一个操作”原则,应该使用第二个方法。
具体取决于您要做什么,但在大多数情况下,嵌套的try/catch表示函数过于复杂(或程序员不太了解异常的工作原理!)。
对于打开文件的情况,我会使用一个IDisposable持有者和using语句,从而避免任何显式的try/catch。
如果您有相关的代码,但这些代码并不一定属于单独的函数,那么这种情况下是否正确呢?
try
{
// Part 1 Code Here
try
{
// Part 2 Code Here
}
catch (Exception ex)
{
// Error from Part 2
}
}
catch (Exception ex)
{
// Error from Part 1
}
try
{
try
{
DoEverything();
}
catch (Exception ex)
{
// Log the exception here
}
}
catch (Exception ex)
{
// Wow, even the log is broken ...
}
//create a switch here and set it to 0
try
{
DoChunk1();
//looks good. set the switch to 1
}
catch (Exception ex)
{
// Log the exception here
}
// 检查开关,如果此时仍为零,则可以在此处停止程序;否则将开关设置回零并执行下一个try catch语句。完全同意按照上述方式分解它们
try { DoChunk2(); //看起来不错。将开关设置为1 } catch (Exception ex) { // 在此处记录异常 }
try
{
----
}
catch
{
try
{
---
}
catch
{
---
}
}