我什么时候应该创建一个析构函数?

时间:2011-02-04 13:55:31

标签: c# destructor

例如:

public class Person
{
    public Person()
    {
    }

    ~Person()
    {
    }
}

我应该何时手动创建析构函数? 什么时候需要创建析构函数?

7 个答案:

答案 0 :(得分:219)

更新:这个问题是the subject of my blog in May of 2015。谢谢你这个好问题!请参阅博客,了解人们通常认为最终确定的一长串谎言。

  

我应该何时手动创建析构函数?

几乎没有。

通常,当您的类持有一些昂贵的非托管资源时,只会创建一个析构函数,该资源必须在对象消失时进行清理。最好使用一次性模式以确保清理资源。然后,析构函数基本上是一种保证,即如果对象的使用者忘记处置它,那么资源最终仍会得到清理。 (也许。)

如果您使析构函数非常小心并且了解垃圾收集器的工作原理。析构函数非常奇怪

  • 他们没有在你的线程上运行;他们在自己的线程上运行。不要造成死锁!
  • 从析构函数抛出的未处理异常是个坏消息。它是在自己的线程上;谁会抓住它?
  • 在构造函数启动后,可以在对象上调用析构函数,但构造函数完成之前。正确编写的析构函数不会依赖于构造函数中建立的不变量。
  • 析构函数可以“复活”一个对象,使一个死对象再次活着。这真的很奇怪。不要这样做。
  • 析构函数可能永远不会运行;你不能依赖于计划完成的对象。 可能是,但这不是保证。

在析构函数中几乎没有任何通常为真的东西。真的,非常小心。编写正确的析构函数非常困难。

  

什么时候需要创建析构函数?

测试处理析构函数的编译器部分时。我从来不需要在生产代码中这样做。我很少编写操纵非托管资源的对象。

答案 1 :(得分:17)

它被称为“终结器”,您通常只应为其状态(即:字段)包含非托管资源(即:通过p / invoke调用检索的句柄的指针)的类创建一个。但是,在.NET 2.0及更高版本中,实际上有更好的方法来处理非托管资源的清理:SafeHandle。鉴于此,您几乎不需要再次编写终结器。

答案 2 :(得分:8)

除非您的类维护非文件资源(如Windows文件句柄),否则不需要一个。

答案 3 :(得分:3)

它被称为析构函数/终结符,通常在实现Disposed模式时创建。

当你的类用户忘记调用Dispose时,这是一个后备解决方案,以确保(最终)你的资源被释放,但你不能保证何时调用析构函数。

在此Stack Overflow question中,接受的答案正确显示了如何实现配置模式。只有当您的类包含垃圾回收器无法自行清理的任何未经处理的资源时,才需要这样做。

一个好的做法是不实现终结器而不给该类用户手动处理对象以立即释放资源的可能性。

答案 4 :(得分:3)

当您拥有非托管资源时,您需要确保在对象消失时清理它们。好的例子是COM对象或文件处理程序。

答案 5 :(得分:2)

我使用了析构函数(仅用于调试目的),以查看是否正在从WPF应用程序范围内的内存中清除对象。我不确定垃圾收集是否真正从内存中清除对象,这是一种很好的验证方法。

答案 6 :(得分:0)

析构函数提供了一种释放封装在类中的非托管资源的隐式方法,当GC转向它时它们会被调用,并且它们隐式调用基类的Finalize方法。如果您使用了大量非托管资源,最好通过IDisposable接口提供一种释放这些资源的显式方法。请参阅C#编程指南:http://msdn.microsoft.com/en-us/library/66x5fx1b.aspx