决赛选手有什么用?

发布于 2024-07-17 07:26:36 字数 72 浏览 8 评论 0原文

我已经用 .NET 编程四年了(主要是 C#),并且广泛使用 IDiposable,但我尚未发现需要终结器。 决赛选手有什么用?

I have been programming in .NET for four years (mostly C#) and I use IDiposable extensively, but I am yet to find a need for a finaliser. What are finalisers for?

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

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

发布评论

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

评论(5

不离久伴 2024-07-24 07:26:36

终结器是确保正确清理某些内容的最后一搏,通常为包装非托管资源的对象保留,例如不会被垃圾收集的非托管句柄等。

编写终结器确实很少见。 幸运的是(与IDisposable不同),终结器不需要传播; 因此,如果您有一个带有终结器的 ClassA 和一个包装 ClassAClassB,则 ClassB 不需要终结器 - 但很可能 ClassAClassB 都会实现 IDisposable

对于托管代码,IDisposable 通常就足够了。 即使您没有正确清理,最终托管对象也会被收集(假设它们已被释放)。

A finalizer is a last ditch attempt to ensure that something is cleaned up correctly, and is usually reserved for objects that wrap unmanaged resources, such as unmanaged handles etc that won't get garbage collected.

It is rare indeed to write a finalizer. Fortunately (and unlike IDisposable), finalizers don't need to be propagated; so if you have a ClassA with a finalizer, and a ClassB which wraps ClassA, then ClassB does not need a finalizer - but quite likely both ClassA and ClassB would implement IDisposable.

For managed code, IDisposable is usually sufficient. Even if you don't clean up correctly, eventually the managed objects will get collected (assuming they are released).

天涯沦落人 2024-07-24 07:26:36

终结器仅用于释放非托管资源,例如 GDI 位图句柄。 如果您不分配任何非托管资源,则不需要终结器。 一般来说,接触终结器中的任何托管对象都是一个坏主意,因为无法保证终结的顺序。

使用终结器的另一种有用技术是在应用程序需要时断言已调用 Dispose。 这可以帮助捕获 DEBUG 构建中的编码错误:

void Dispose()
{
  GC.SuppressFinalize(this);
}
#if DEBUG
~MyClass()
{
  Debug.Fail("Dispose was not called.");
}
#endif

Finalizers are only for freeing unmanaged resources like GDI bitmap handles for example. If you don't allocate any unmanaged resources then you don't need finalizers. In general it's a bad idea to touch any managed object in a finalizer because the order of finalization is not guaranteed.

One other useful technique using a finalizer is to assert that Dispose has been called when the application is required to do so. This can help catch coding errors in a DEBUG build:

void Dispose()
{
  GC.SuppressFinalize(this);
}
#if DEBUG
~MyClass()
{
  Debug.Fail("Dispose was not called.");
}
#endif
天冷不及心凉 2024-07-24 07:26:36

终结器是一种释放不受垃圾收集器控制的资源的机制,例如非托管句柄。 虽然 Dispose 可能会执行此操作,但不能保证消费者会调用​​它。

Finalizers are meant as a mechanism to release resources not controlled by garbage collector, like an unmanaged handle. While Dispose might do it, it isn't guaranteed that the consumer will call it.

我不吻晚风 2024-07-24 07:26:36

终结器用于清理未处理的资源。

IE 中,没有什么强制要求您必须调用 Dispose(),但终结器会由垃圾收集器自动调用。

不应依赖此功能,因为无法保证垃圾收集何时(或是否)到达您的对象。

Finalizers are for cleaning up resources if they were not disposed.

IE, nothing enforces that you ever call Dispose(), but Finalizers are called automatically by the garbage collector.

This functionality should not be relied upon, as there is no guarantee when (or if) garbage collection will get to your object.

芯好空 2024-07-24 07:26:36

维基百科

...终结器是一段代码
确保某些必要的行动
当获取资源时采取...
不再使用[因为
拥有的对象已经是垃圾
已收集]

则很可能会出现内存泄漏,因为无法保证所有者实际上会调用 Dispose()。

MS 本身建议您在实现者中编写类似的内容:

    public void Dispose()
    {
        this.Dispose(true);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (!this.isDisposed)
        {
            if (disposing)
            {
                GC.SuppressFinalize(this);
            }
        }
        //Dispose of resources here
        this.isDisposed = true;
    }

    ~DisposableSafe()
    {
        this.Dispose(false);
    }

    private bool isDisposed = false;

就个人而言,我无法忍受复制粘贴,因此我倾向于将其包装在抽象类中以供重用。

Wikipedia says:

...a finalizer is a piece of code that
ensures that certain necessary actions
are taken when an acquired resource...
is no longer being used [because the
owning object has been garbage
collected]

And if you're not using a finaliser when you're writing IDisposables you've quite possibly got memory leaks, because there's no guarantee an owner is actually going to call Dispose().

MS themselves recommend you write something similar to this into your implementers:

    public void Dispose()
    {
        this.Dispose(true);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (!this.isDisposed)
        {
            if (disposing)
            {
                GC.SuppressFinalize(this);
            }
        }
        //Dispose of resources here
        this.isDisposed = true;
    }

    ~DisposableSafe()
    {
        this.Dispose(false);
    }

    private bool isDisposed = false;

Personally, I can't stand the copy-paste so I tend to wrap that in an abstract class for reuse.

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