无论是否发生异常,finally块中的代码都将被执行。当需要执行某些必须运行的清理函数(例如关闭连接)时,这非常方便。
现在,我猜测您的问题是为什么应该这样做:
try
{
doSomething();
}
catch
{
catchSomething();
}
finally
{
alwaysDoThis();
}
当你可以做到这一点时:
try
{
doSomething();
}
catch
{
catchSomething();
}
alwaysDoThis();
答案是,很多时候 catch 语句中的代码要么重新抛出异常,要么跳出当前函数。如果 catch 语句中的代码执行了返回或抛出新异常操作,则 "alwaysDoThis();" 调用不会被执行。using
块来创建和释放资源,而不是使用finally
,并在语句内部使用try catch块(using
不能替代try catch
)。这样做的唯一优点是,当您离开块时,立即释放资源(您可能会忘记使用finally
),但我相信有很多情况下您可能更愿意使用finally
。请参见https://dev59.com/43VC5IYBdhLWcg3wliGe#248984。 - Aaron Newton虽然已经提出了使用try-finally的大多数优点,但是我想再加上一个:
try
{
// Code here that might throw an exception...
if (arbitraryCondition)
{
return true;
}
// Code here that might throw an exception...
}
finally
{
// Code here gets executed regardless of whether "return true;" was called within the try block (i.e. regardless of the value of arbitraryCondition).
}
这种行为使其在各种情况下非常有用,特别是当您需要执行清理(释放资源)时,尽管在这种情况下使用using块通常更好。
即使你在 catch 块中没有处理异常,finally 块也将被执行。
每当您使用不受管控的代码请求,如流读取器、数据库请求等,并且想要捕获异常时,请使用try-catch-finally,并在finally中关闭流、数据读取器等。如果您没有这样做,当出现错误时连接将无法关闭,这在数据库请求中非常糟糕。
SqlConnection myConn = new SqlConnection("Connectionstring");
try
{
myConn.Open();
//make na DB Request
}
catch (Exception DBException)
{
//do somehting with exception
}
finally
{
myConn.Close();
myConn.Dispose();
}
如果您不想捕获错误,请使用
using (SqlConnection myConn = new SqlConnection("Connectionstring"))
{
myConn.Open();
//make na DB Request
myConn.Close();
}
如果出现错误,连接对象将自动释放,但如果您未捕获错误,则不会发生此操作。
最终语句可以甚至在返回后执行。
private int myfun()
{
int a = 100; //any number
int b = 0;
try
{
a = (5 / b);
return a;
}
catch (Exception ex)
{
Response.Write(ex.Message);
return a;
}
// Response.Write("Statement after return before finally"); -->this will give error "Syntax error, 'try' expected"
finally
{
Response.Write("Statement after return in finally"); // --> This will execute , even after having return code above
}
Response.Write("Statement after return after finally"); // -->Unreachable code
}
finally
,如下所示:
try {
// do something risky
} catch (Exception ex) {
// handle an exception
} finally {
// do any required cleanup
}
无论您的try...catch
块是否抛出异常,都可以保证执行代码的机会。
这使得它非常适合释放资源、数据库连接、文件句柄等操作。
我将解释如何使用finally处理文件读取异常的示例。
try{
StreamReader strReader = new StreamReader(@"C:\Ariven\Project\Data.txt");
Console.WriteLine(strReader.ReadeToEnd());
StreamReader.Close();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
在上面的例子中,如果名为Data.txt的文件丢失,则会抛出异常并得到处理,但称为StreamReader.Close();
的语句将永远不会被执行。
因此,与读取器相关联的资源从未被释放。
StreamReader strReader = null;
try{
strReader = new StreamReader(@"C:\Ariven\Project\Data.txt");
Console.WriteLine(strReader.ReadeToEnd());
}
catch (Exception ex){
Console.WriteLine(ex.Message);
}
finally{
if (strReader != null){
StreamReader.Close();
}
}
愉快的编码 :)
注意: "@"用于创建原样字符串,以避免出现"无法识别的转义序列"错误。 @符号意味着直接读取该字符串,不要解释控制字符。
假设你需要将光标设置回默认指针,而不是等待(沙漏)指针。如果在设置光标之前抛出异常,并且不直接崩溃应用程序,则可能会留下令人困惑的光标。
try
{
// exception (or not)
}
finally
{
// clean up always
}