析构函数中的异常(c#)?

时间:2012-03-28 07:32:51

标签: c# exception .net-4.0 garbage-collection destructor

我有这堂课:

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)我将用TryCache包裹它 - 我会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(析构函数)中的异常

4 个答案:

答案 0 :(得分:14)

这实际上取决于.NET框架

例如,在.NET 2.NET 4中,您的申请将被终止

  

如果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.

编辑

根据documentation

  

如果Finalize或者Finalize的覆盖引发异常,那么   运行时不由覆盖默认值的应用程序托管   策略,运行时终止进程,没有活动的try-finally   执行块或终结器。此行为可确保进程   如果终结者不能释放或破坏资源,则完整性。

换句话说:不要在Finalizer中调用可能失败的东西。相反,请使用Dispose,并确保调用它。

希望这有帮助。