无论内部是什么,最终块(几乎)总是被执行,那么将代码封装到其中或将其保持未封闭之间的区别是什么?
答案 0 :(得分:374)
无论是否存在异常,finally块中的代码都将被执行。这对于某些内务处理功能非常方便,您需要始终像关闭连接那样运行。
现在,我猜测你的问题是为什么你应该这样做:
try
{
doSomething();
}
catch
{
catchSomething();
}
finally
{
alwaysDoThis();
}
当你能做到这一点时:
try
{
doSomething();
}
catch
{
catchSomething();
}
alwaysDoThis();
答案是,很多时候catch语句中的代码会重新抛出异常或者中断当前函数。用后面的代码,“alwaysDoThis();”如果catch语句中的代码发出返回或抛出新异常,则调用将不会执行。
答案 1 :(得分:57)
使用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).
}
此行为使其在各种情况下非常有用,尤其是当您需要执行清理(处置资源)时,尽管在这种情况下使用块通常更好。
答案 2 :(得分:11)
任何时候使用非托管代码请求,如流读取器,数据库请求等;并且你想捕获异常然后使用try catch finally并在最后关闭流,数据读取器等,如果你没有错误连接没有关闭,这对db请求来说真的很糟糕< / p>
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();
}
如果出现错误,连接对象将自动处理,但您不会捕获错误
答案 3 :(得分:10)
因为即使你没有在catch块中处理异常,finally也会被执行。
答案 4 :(得分:7)
finally
,如:
try {
// do something risky
} catch (Exception ex) {
// handle an exception
} finally {
// do any required cleanup
}
是保证在try..catch
阻止后执行代码的机会,无论您的try块是否引发异常。
这使得它非常适合发布资源,数据库连接,文件句柄等等。
答案 5 :(得分:7)
最后语句甚至可以在返回后执行。
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
}
答案 6 :(得分:3)
通过使用finally
块,您可以清除try
块中分配的所有资源,即使try
块中发生异常,您也可以运行代码。通常,当控件离开try语句时,finally
块的语句会运行。控制权的转移可能是由于正常执行,执行break, continue, goto, or return
语句或从try
语句传播异常而发生的。
在处理的异常中,保证运行关联的finally
块。但是,如果未处理异常,则finally
块的执行取决于如何触发异常展开操作。反过来,这取决于您的计算机的设置方式。有关详细信息,请参阅Unhandled Exception Processing in the CLR。
通常,当未处理的异常结束应用程序时,无论finally
块是否运行都不重要。但是,如果在finally
块中的语句即使在这种情况下也必须运行,一种解决方案是在catch
语句中添加try-finally
块。或者,您可以捕获可能在调用堆栈上方try
语句的try-finally
块中抛出的异常。也就是说,您可以在调用包含try-finally
语句的方法的方法中,或在调用该方法的方法中,或在调用堆栈的任何方法中捕获异常。如果未捕获到异常,则finally
块的执行取决于操作系统是否选择触发异常展开操作。
public class ThrowTestA
{
static void Main()
{
int i = 123;
string s = "Some string";
object obj = s;
try
{
// Invalid conversion; obj contains a string, not a numeric type.
i = (int)obj;
// The following statement is not run.
Console.WriteLine("WriteLine at the end of the try block.");
}
finally
{
// To run the program in Visual Studio, type CTRL+F5. Then
// click Cancel in the error dialog.
Console.WriteLine("\nExecution of the finally block after an unhandled\n" +
"error depends on how the exception unwind operation is triggered.");
Console.WriteLine("i = {0}", i);
}
}
// Output:
// Unhandled Exception: System.InvalidCastException: Specified cast is not valid.
//
// Execution of the finally block after an unhandled
// error depends on how the exception unwind operation is triggered.
// i = 123
}
在下面的示例中,TryCast方法的异常捕获在调用堆栈更远的方法中。 C#
public class ThrowTestB
{
static void Main()
{
try
{
// TryCast produces an unhandled exception.
TryCast();
}
catch (Exception ex)
{
// Catch the exception that is unhandled in TryCast.
Console.WriteLine
("Catching the {0} exception triggers the finally block.",
ex.GetType());
// Restore the original unhandled exception. You might not
// know what exception to expect, or how to handle it, so pass
// it on.
throw;
}
}
public static void TryCast()
{
int i = 123;
string s = "Some string";
object obj = s;
try
{
// Invalid conversion; obj contains a string, not a numeric type.
i = (int)obj;
// The following statement is not run.
Console.WriteLine("WriteLine at the end of the try block.");
}
finally
{
// Report that the finally block is run, and show that the value of
// i has not been changed.
Console.WriteLine("\nIn the finally block in TryCast, i = {0}.\n", i);
}
}
// Output:
// In the finally block in TryCast, i = 123.
// Catching the System.InvalidCastException exception triggers the finally block.
// Unhandled Exception: System.InvalidCastException: Specified cast is not valid.
}
答案 7 :(得分:3)
我将用文件阅读器异常示例
解释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(); } }
快乐编码:)
注意:强> &#34; @&#34;用于创建逐字字符串,以避免&#34;无法识别的转义序列&#34;的错误。 @符号表示按字面意思读取该字符串,否则不解释控制字符。
答案 8 :(得分:2)
假设您需要将光标设置回默认指针而不是等待(沙漏)光标。如果在设置光标之前抛出异常,并且没有彻底崩溃应用程序,则可能会留下令人困惑的光标。
答案 9 :(得分:2)
The finally block对于清理try块中分配的任何资源以及运行任何必须执行的代码(即使存在异常)也很有用。无论try块如何退出,控制总是传递给finally块。
答案 10 :(得分:2)
有时你不想处理异常(没有catch块),但你想要执行一些清理代码。
例如:
try
{
// exception (or not)
}
finally
{
// clean up always
}
答案 11 :(得分:1)
例如,可能是因为如果抛出错误就停止执行,但是仍然想要清理资源,例如打开文件,数据库连接等。
答案 12 :(得分:1)
Finally块的控制流程在Try或Catch块之后。
[1. First Code]
[2. Try]
[3. Catch]
[4. Finally]
[5. After Code]
有异常 1> 2&gt; 3> 4>五 如果3有一个Return语句 1> 2&gt; 3> 4
没有例外 1> 2&gt; 4>五 如果2有一个return语句 1> 2&gt; 4
答案 13 :(得分:0)
最后阻止
如果在退出Try
结构之前必须运行一个或多个语句,请使用Finally
块。 Finally
块对于运行任何必须执行的代码非常有用,即使存在异常也是如此。无论Finally
... Try
块如何退出,控制都会传递到Catch
块。控制权在传递出Finally
... Try
结构之前传递到Catch
块。即使在Try
结构内的任何位置发生异常,也是如此。即使您的代码在Finally
或Return
块中遇到Try
语句,Catch
块中的代码也会运行。
将执行显式转移到Finally
块无效。
从Finally
块传输执行无效,除非是例外。
答案 14 :(得分:0)
如documentation中所述:
catch和finally一起使用的常见用法是在try块中获取和使用资源,在catch块中处理特殊情况,然后在finally块中释放资源。
也值得一读this,其中指出:
一旦找到匹配的catch子句,系统准备将控制权转移到catch子句的第一条语句。在开始执行catch子句之前,系统首先按顺序执行与try语句相关联的所有finally子句,其嵌套程度远大于捕获异常的子句。
因此很明显,即使先前的finally
子句具有catch
语句,驻留在return
子句中的代码也将被执行。