使用解构器错了吗?

时间:2011-04-07 13:19:14

标签: c# garbage-collection finalizer

我将一些文件写入c#中的临时位置。然后将它们呈现为pdf缩略图。当对象被销毁时我希望清理位置,所以在这种情况下使用解构器是否正常?

    ~Foo()
    {
        try
        {
            Directory.Delete(path, true);
        }
        catch (IOException ex)
        {
            Console.WriteLine("exception: " + ex.Message + " . from: Foo_Closing");
        }

8 个答案:

答案 0 :(得分:7)

尽管它与C ++析构函数具有相同的语法,但是C#中的终结器在最终化时对象被垃圾收集时运行 - 这将对性能产生影响,因为GC必须运行单独的线程来运行所有终结器,为此你的对象实例将比必要的寿命更长。

如果你不是必须的话,你不应该使用它 - 例外是当你必须处理资源时,在这种情况下你的类也应该实现IDisposable。这样,您的班级的消费者就可以将其打包到using块中,该块会调用Dispose() - 这是您应该拆除资源的地方。

答案 1 :(得分:3)

您应该实现IDisposable接口,并在那里进行清理。

答案 2 :(得分:3)

解构器(也称为析构函数或终结器)的问题在于,您无法预测它们何时运行,因为它们是由垃圾收集器调用的。为了获得可预测的行为,您应该实现IDisposable并明确调用Dispose(或使用using块中的对象)

如果未明确调用析构函数,也可以从析构函数中调用Dispose。有关建议使用的模式,请参阅this page

答案 3 :(得分:2)

我可能只是使用环境的临时文件/文件夹位置,以便用户或管理员可以在正常的内务处理过程中清理这些文件。

不要打扰这样做,因为它很糟糕 - 文件夹在那里删除真的那么重要吗?

答案 4 :(得分:2)

尽量避免使用终结器。您无法控制它们何时被调用,并且它们会导致性能损失,因为运行时需要特别使用终结器来处理对象。通常,如果您有本机对象句柄或需要清理的其他本机资源,则应该只实现终结器。

相反,在类上实现IDisposable接口,将清理代码移到Dispose方法,并确保所有客户端都调用Dispose方法(using语句用于此目的)。

答案 5 :(得分:2)

实施IDisposable接口:

public class tester : IDisposable
{
    #region IDisposable Members

    public void Dispose()
    {
        //cleanup code here
    }

    #endregion
}

using (tester t = new tester())
{

}
//tester now disposed 

但不要忘记this gem of knowledge from MSDN

  

因为Dispose方法必须是   明确调用,对象   实现IDisposable也必须   实现终结器来处理   当Dispose不是时释放资源   称为

因此,您还应该实现终结器和IDisposable接口,同时要记住两者都将被调用。

答案 6 :(得分:1)

为什么不使用IDisposable inteface,然后你可以用“using”包装你的调用,Dispose()将执行它需要执行的所有清理

public class Foo : IDisposable { public void Dispose() { //Clean up here}
}

using (foo = new Foo() ) { //consume foo here }

答案 7 :(得分:0)