实际使用finally块

时间:2010-05-20 07:41:33

标签: c# memory-management idisposable

我向我的朋友询问了这个问题,他说它用于销毁在异常处理期间创建的对象。但是在c#GC中有用于销毁这类未使用的对象,那么finally块的实际用途是什么。告诉我一个与此相关的场景。

8 个答案:

答案 0 :(得分:14)

无论是否发生异常,都可以保证运行。

通常情况下,如果有某种资源需要确保正确发布,则可以使用它。与创建的对象during the exception handling无关。但是说你有某种类型的连接到数据库或文件句柄。

如果它是实现IDisposable的托管对象,则更好的方法通常是using关键字。

答案 1 :(得分:11)

当不再引用GC时,GC将清除托管资源(应用程序在内存中创建的对象)。这不包括文件句柄,网络资源,数据库连接等内容......您必须finally块中自行清除它们或冒险不清除它们(尽管大多数都会清除)最终)。

OR ,更常见的是:

许多需要处理的非托管资源的类实现了IDisposable接口。这意味着您可以将代码包装在using块中,并确保将清除非托管资源(当它超出范围时调用对象的Dispose()方法)。

使用finally块的一个很好的示例是使用Office互操作库时。假设您打开Microsoft Word,运行一些代码,代码失败......无论是否发生错误,Word 始终 都需要关闭。因此,我会将结束代码放在finally块中。

答案 2 :(得分:5)

GC将最终销毁对象,这是真的。但是当你拥有最好尽快释放的非内存资源时,finally块很有用。例如,如果您有数据库连接,则不希望连接在终结器运行之前保持打开(可能是不确定的)很长时间,因此您将其放在using块中(这只是一个合成的) try ... finally块的糖:

using(var conn = new SqlConnection(...))
{
    // use the connection
}

这是(基本上)的语法糖:

var conn = new SqlConnection(...);
try
{
    // use the connection
}
finally
{
    conn.Dispose();
}

现在,如果您没有finally / using,那么当对象的终结器运行时,连接将最终处理,但是因为您没有知道会发生什么,最好在using块中包装对象的使用,以确保连接在不再需要时立即关闭。

答案 3 :(得分:1)

最终用于确保执行某些操作,无论是否发生异常。

其中一个用途 - 尽管不是很“优雅” - 是在先前打开的数据库连接上调用close()。更多通常用于GC无法清除的所有内容(例如数据库或网络连接)。

http://msdn.microsoft.com/en-en/library/zwc8s4fz(VS.80).aspx

答案 4 :(得分:1)

当你想要一段代码运行时,无论是否发生异常,都会使用

finally块。例如,关闭数据库连接。

答案 5 :(得分:0)

最后阻止不仅仅是释放内存! 想想这个案子: 在'尝试'块中你 - 1.打开与DB的连接 2.执行查询 第2步因例外而失败。 但是,在任何情况下,您都应该关闭与DB的连接 - 正确的位置是在finally块中。

这只是一个例子。有许多不同的情况可能需要finally块。

答案 6 :(得分:0)

垃圾收集器将在适当的时候收集托管资源。对于那些也持有非托管资源(如网络资源,数据库连接或文件句柄等)的人来说,他们通常支持IDisposable接口,如果正确完成,仍然会通过终结者释放资源;但是Dispose() finally允许您在释放这些资源时控制

如果您只有一个IDisposable对象,那么using块可能更合适,但如果您(a)需要处理块内抛出的异常,则陪审团仍然不在,或(b)将几个IDisposable个对象全部一起使用(例如SqlConnectionSqlCommand ...)

答案 7 :(得分:0)

除了提到的其他场景之外,另一个常见的场景是锁。 synclock语句调用Monitor.Enter并执行一段代码;然后,它会使用finally块来呼叫Monitor.Exit。如果代码在没有调用Monitor.Exit的情况下离开块,那么任何其他尝试使用锁保护的资源都将被永久阻止。

顺便说一句,即使在synclock内发生了一些不好的事情,使得被锁定的资源被认为是腐败而且没有被使用,保留锁定并不是处理这种情况的好方法。一个更好的方法是让synclock内的代码显式地使对象失效,使得等待锁的任何其他代码都被授予访问权限,然后在尝试使用无效对象时最终抛出异常。 / p>