我有这堂课:
public class TempFileRef
{
public readonly string FilePath;
public TempFileRef(string filePath)
{
FilePath = filePath;
}
~TempFileRef()
{
File.Delete(FilePath); //<== what happens if exception ?
}
}
问题:
如果析构函数中存在异常,会发生什么?
1)它会破坏F-Queue中的其他终结吗?
2)我将用Try
和Cache
包裹它 - 我会NEVER
知道有错误
3)what
我应该在这做什么?
基于"if I **forget** to call the Dispose method - so the GC will do it eventually.... it is better later then never..."
的{{3}}模式。所以我的问题是特别关于Finilize(析构函数)中的异常
答案 0 :(得分:14)
这实际上取决于.NET框架
如果Finalize或Finalize的覆盖引发异常,而运行时则不会 由覆盖默认值的应用程序托管 策略,运行时终止进程,没有活动的try-finally 执行块或终结器。此行为可确保进程 如果终结者不能释放或破坏资源,则完整性。
与.NET 1相反,只有终结器才会终止,您的应用程序将继续运行:
如果Finalize或者Finalize的覆盖引发了异常,那么 运行时忽略该异常,终止该Finalize方法,以及 继续完成最后的过程。
你实际上要做的是实现一个IDisposable
模式,所以将这项工作留给一个finilazer,在名为Dispose
的程序中进行。
答案 1 :(得分:9)
来自MSDN:
析构函数执行期间发生的异常值得特别 提到。如果在析构函数执行期间发生异常,那么 异常没有被捕获,然后执行该析构函数 终止并调用基类的析构函数(如果有的话)。如果 没有基类(如对象类型的情况)或者是否存在 没有基类析构函数,然后抛弃异常。
答案 2 :(得分:6)
不要删除终结器中的文件,而应考虑实现IDisposable
接口。
析构函数执行期间发生的异常值得特别 提到。如果在析构函数执行期间发生异常,那么 异常没有被捕获,然后执行该析构函数 终止并调用基类的析构函数(如果有的话)。如果 没有基类(如对象类型的情况)或者是否存在 没有基类析构函数,然后抛弃异常。
http://msdn.microsoft.com/en-us/library/aa664609%28v=vs.71%29.aspx
答案 3 :(得分:0)
不要使用析构函数,它不是C++
,使用您应该实现的Dispose()
接口IDisposbale
方法。从您的代码中明确地调用Dispose(),或者将您的类与using
一起使用,例如(比如说)
using(var tempRef = new TempFileRef())
{
//do something here
} //Dispose will be called after this line.
编辑
如果Finalize或者Finalize的覆盖引发异常,那么 运行时不由覆盖默认值的应用程序托管 策略,运行时终止进程,没有活动的try-finally 执行块或终结器。此行为可确保进程 如果终结者不能释放或破坏资源,则完整性。
换句话说:不要在Finalizer中调用可能失败的东西。相反,请使用Dispose,并确保调用它。
希望这有帮助。