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

发布于 2024-10-16 01:16:17 字数 158 浏览 3 评论 0原文

例如:

public class Person
{
    public Person()
    {
    }

    ~Person()
    {
    }
}

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

For example:

public class Person
{
    public Person()
    {
    }

    ~Person()
    {
    }
}

When should I manually create a destructor?
When have you needed to create a destructor?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

笑红尘 2024-10-23 01:16:17

更新:这个问题是主题我的博客于 2015 年 5 月。感谢您提出的好问题!请参阅该博客,了解人们普遍认为的关于最终确定的一长串谎言。

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

几乎从来没有。

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

如果您创建析构函数,请非常小心了解垃圾收集器的工作原理。析构函数真的很奇怪

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

通常正确的情况在析构函数中几乎都不是正确的。一定要非常非常小心。编写正确的析构函数非常困难。

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

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

UPDATE: This question was the subject of my blog in May of 2015. Thanks for the great question! See the blog for a long list of falsehoods that people commonly believe about finalization.

When should I manually create a destructor?

Almost never.

Typically one only creates a destructor when your class is holding on to some expensive unmanaged resource that must be cleaned up when the object goes away. It is better to use the disposable pattern to ensure that the resource is cleaned up. A destructor is then essentially an assurance that if the consumer of your object forgets to dispose it, the resource still gets cleaned up eventually. (Maybe.)

If you make a destructor be extremely careful and understand how the garbage collector works. Destructors are really weird:

  • They don't run on your thread; they run on their own thread. Don't cause deadlocks!
  • An unhandled exception thrown from a destructor is bad news. It's on its own thread; who is going to catch it?
  • A destructor may be called on an object after the constructor starts but before the constructor finishes. A properly written destructor will not rely on invariants established in the constructor.
  • A destructor can "resurrect" an object, making a dead object alive again. That's really weird. Don't do it.
  • A destructor might never run; you can't rely on the object ever being scheduled for finalization. It probably will be, but that's not a guarantee.

Almost nothing that is normally true is true in a destructor. Be really, really careful. Writing a correct destructor is very difficult.

When have you needed to create a destructor?

When testing the part of the compiler that handles destructors. I've never needed to do so in production code. I seldom write objects that manipulate unmanaged resources.

就此别过 2024-10-23 01:16:17

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

It's called a "finalizer", and you should usually only create one for a class whose state (i.e.: fields) include unmanaged resources (i.e.: pointers to handles retrieved via p/invoke calls). However, in .NET 2.0 and later, there's actually a better way to deal with clean-up of unmanaged resources: SafeHandle. Given this, you should pretty much never need to write a finalizer again.

小镇女孩 2024-10-23 01:16:17

除非您的类维护 Windows 文件句柄等非托管资源,否则您不需要它。

You don't need one unless your class maintains unmanaged resources like Windows file handles.

枉心 2024-10-23 01:16:17

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

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

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

一个好的做法是,在不让类的用户能够手动处理对象以立即释放资源的情况下,不要实现终结器。

It's called a destructor/finalizer, and is usually created when implementing the Disposed pattern.

It's a fallback solution when the user of your class forgets to call Dispose, to make sure that (eventually) your resources gets released, but you do not have any guarantee as to when the destructor is called.

In this Stack Overflow question, the accepted answer correctly shows how to implement the dispose pattern. This is only needed if your class contain any unhandeled resources that the garbage collector does not manage to clean up itself.

A good practice is to not implement a finalizer without also giving the user of the class the possibility to manually Disposing the object to free the resources right away.

絕版丫頭 2024-10-23 01:16:17

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

I have used a destructor (for debug purposes only) to see if an object was being purged from memory in the scope of a WPF application. I was unsure if garbage collection was truly purging the object from memory, and this was a good way to verify.

执笏见 2024-10-23 01:16:17

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

When you have unmanaged resources and you need to make sure they will be cleaned up when your object goes away. Good example would be COM objects or File Handlers.

幼儿园老大 2024-10-23 01:16:17

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

Destructors provide an implicit way of freeing unmanaged resources encapsulated in your class, they get called when the GC gets around to it and they implicitly call the Finalize method of the base class. If you're using a lot of unmanaged resources it is better to provide an explicit way of freeing those resources via the IDisposable interface. See the C# programming guide: http://msdn.microsoft.com/en-us/library/66x5fx1b.aspx

琴流音 2024-10-23 01:16:17

答案:
当您必须释放非托管资源时,例如文件句柄、数据库连接等。

// Example
public class Person
{
    private FileStream _fileStream;

    public Person()
    {
        _fileStream = new FileStream("test.txt", FileMode.Open);
    }

    ~Person()
    {
        _fileStream.Close();
    }
}

说明:
当对象被垃圾回收时,析构函数被调用。当程序员销毁对象时,不会调用它。当该对象不再被任何其他对象引用时调用它。当对象不再处于作用域内时调用它。当对象不再位于内存中时调用它。

Answer:
When you have to release unmanaged resources, like file handles, database connections, etc.

// Example
public class Person
{
    private FileStream _fileStream;

    public Person()
    {
        _fileStream = new FileStream("test.txt", FileMode.Open);
    }

    ~Person()
    {
        _fileStream.Close();
    }
}

Explanation:
The destructor is called when the object is garbage collected. It is not called when the object is destroyed by the programmer. It is called when the object is no longer referenced by any other object. It is called when the object is no longer in scope. It is called when the object is no longer in memory.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文