我向我的朋友询问了这个问题,他说它用于销毁在异常处理期间创建的对象。但是在c#GC中有用于销毁这类未使用的对象,那么finally块的实际用途是什么。告诉我一个与此相关的场景。
答案 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
个对象全部一起使用(例如SqlConnection
,SqlCommand
...)
答案 7 :(得分:0)
除了提到的其他场景之外,另一个常见的场景是锁。 synclock
语句调用Monitor.Enter
并执行一段代码;然后,它会使用finally
块来呼叫Monitor.Exit
。如果代码在没有调用Monitor.Exit
的情况下离开块,那么任何其他尝试使用锁保护的资源都将被永久阻止。
顺便说一句,即使在synclock
内发生了一些不好的事情,使得被锁定的资源被认为是腐败而且没有被使用,保留锁定并不是处理这种情况的好方法。一个更好的方法是让synclock内的代码显式地使对象失效,使得等待锁的任何其他代码都被授予访问权限,然后在尝试使用无效对象时最终抛出异常。 / p>