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

177 c# destructor

例如:

public class Person
{
    public Person()
    {
    }

    ~Person()
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

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

Eri*_*ert 229

更新:这个问题是我2015年5月的博客主题.谢谢你这个好问题!请参阅博客,了解人们通常认为最终确定的一长串谎言.

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

几乎从不.

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

如果你让析构函数非常小心理解垃圾收集器是如何工作的.析构函数真的很奇怪:

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

在析构函数中几乎没有什么通常是正确的.真的,非常小心.编写正确的析构函数非常困难.

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

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

  • @configurator:没有.假设一个对象的第三个字段初始值设定项使用一个称为静态方法的终结器,该方法会引发异常.第四个字段初始化程序何时运行?决不.但该对象仍然已分配,必须最终确定.哎呀,你甚至不能保证当dtor运行时,double类型的字段被*完全*初始化.可能有一个线程在写入double的中途中止,现在终结器必须处理半初始化的半零双. (12认同)
  • 很棒的文章埃里克.道具 - >"额外奖励乐趣:在调试器中运行程序时,运行时使用不太激进的代码生成和不太积极的垃圾收集,因为调试对象突然消失,即使引用该对象的变量在范围内.这意味着如果你有一个过早定型对象的bug,你可能无法在调试器中重现那个bug!" (2认同)

Nic*_*oiu 17

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

  • @ThomasEding - [是的](http://msdn.microsoft.com/en-us/library/0s71x931(v = vs.80).aspx).C#使用析构函数语法,但它实际上创建了[finalizer](http://en.wikipedia.org/wiki/Finalizer).[再次](http://msdn.microsoft.com/en-us/library/66x5fx1b.aspx). (25认同)

Joh*_*ers 8

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

  • 嗯,实际上,它被称为析构函数 (5认同)
  • 事实上,C#规范称它为析构函数.有些人认为这是一个错误.http://stackoverflow.com/questions/1872700/the-difference-between-a-destructor-and-a-finalizer (4认同)
  • 现在我很困惑.它是终结者还是析构者? (2认同)
  • @ThomasEding - [是的](http://msdn.microsoft.com/en-us/library/0s71x931(v = vs.80).aspx).C#使用析构函数语法,但它实际上创建了[finalizer](http://en.wikipedia.org/wiki/Finalizer). (2认同)
  • 我喜欢这里的评论,真正的panto :) (2认同)

Øyv*_*hen 5

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

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

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

一个好的做法是不实现终结器,同时也给类的用户提供手动处置对象以立即释放资源的可能性。

  • 其实**是**。感谢您给我投反对票,因为您弄错了。请参阅有关此特定问题的 MSDN 库:http://msdn.microsoft.com/en-us/library/66x5fx1b.aspx (15认同)