Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/290.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如果我的类实现了IDisposable,为什么我需要一个终结器?_C#_.net_C# 3.0 - Fatal编程技术网

C# 如果我的类实现了IDisposable,为什么我需要一个终结器?

C# 如果我的类实现了IDisposable,为什么我需要一个终结器?,c#,.net,c#-3.0,C#,.net,C# 3.0,下面的一次性图案怎么样 using System; public class MyClass : IDisposable { public void Dispose() // Implement IDisposable { //just do the cleanup GC.SuppressFinalize(this); } } 更新 我的意思是说,如果没有未管理的资源,我需要终结器吗?以上的一

下面的一次性图案怎么样

using System;
public class MyClass : IDisposable 
{     
    public void Dispose() 
        // Implement IDisposable     
    {
        //just do the cleanup
        GC.SuppressFinalize(this);
    } 

} 
更新 我的意思是说,如果没有未管理的资源,我需要终结器吗?以上的一次性模式还不够好吗?是的,即使用户/开发人员不调用dispose,GC在默认情况下不调用dispose吗

GC调用dispose和finalizers的顺序如何

有关更多详细信息,请参阅

换句话说,当我们有finalizer时,为什么我们调用
Dispose
,参数为false


从中,似乎总是建议从终结器而不是托管引用中释放非托管资源

始终建议从Dispose方法释放非托管资源。读这篇文章时,我仍然没有领会全部要点

但是如果没有非托管资源,下面的模式应该可以工作


根据msdn.microsoft.com/en-us/magazine/cc163392.aspx#S2、msdn.microsoft.com/en-us/library/fs2xkftw.aspx,建议在finalizer中释放本机资源,并使用dispose()释放所有资源。如果显式调用dispose(),它可以抑制终结器,也就是说,如果没有本机资源,我们就不需要终结器

using System;
public class MyClass : IDisposable 
{ 
    private bool disposed = false;  
    protected virtual void Dispose(bool suppressFinalize) 
    {    
        if (!disposed)
        {
            //Just do the cleanup
            //and release resources
            disposed = true; 
        }
        if (!suppressFinalize)
        {
            GC.SuppressFinalize(this); 
        }
    }
    public void Dispose() 
        // Implement IDisposable     
    {
        Dispose(true);           
    } 
    ~MyClass() // the finalizer
    {     
        Dispose(false);    
    }
} 
因为您可能直接引用了非托管资源(例如Windows句柄),并且即使没有人调用
Dispose
,您也希望释放它们


但这是非常罕见的-通常您只能通过其他托管类型间接引用非托管资源,如果需要,这些托管类型将具有终结器。

Finalization+
IDisposable
在.Net中实际上是两个截然不同的问题,试图通过单个一次性模式来解决

  • 托管资源清理
  • 非托管资源清理
非托管资源是不受CLR和垃圾收集器控制的项。文件句柄、PInvoke返回的内存等项。。。如果这些资源没有被用户代码显式释放,它们将泄漏并在进程生命周期的剩余时间内存在。他们被释放是至关重要的

这就是终结器的作用。它将在CLR收集对象之前在对象上运行。这不需要使用者遵循一次性模式,因此是确保释放非托管资源以防止泄漏的好方法


如果您的代码不包含任何直接持有的非托管资源,则没有理由使用终结器。拥有终结器是持有非托管资源的代码的责任

实现
IDisposable
本身并不能保证调用
Dispose()
。需要添加finalizer的情况非常罕见。如果没有更多的上下文来解释为什么你认为你需要一个终结器,我们怎么可能回答呢?伙计们,请阅读-你不需要像添加终结器那样“需要终结器”。您告诉GC不要(!)完成这个对象,因为它已经完成了。就这么简单。表示对象没有进入终结状态,这意味着gc“run”是释放内存的2的整数。@dasblinkenlight,gc在收集内存时不是调用Dispose吗?比如说,如果我没有未管理的资源,我真的需要终结器吗?如果我没有终结器,会有默认的终结器吗?我需要抑制对终结器的调用吗?@Dreamer否,GC不调用
Dispose
。事实上,
IDisposable
对象和所有其他对象之间确实存在差异。如果您没有对非托管资源的直接引用,那么就不需要终结器,也不需要抑制它。对我来说,这是关于这个主题的“上帝的话:@lukeppulett:是的,我知道那篇文章-但这是处理一个非常普遍的情况。这就是密封类之所以有用的一个原因:大多数模式都变得不必要,因为您不必担心派生类可能需要自己的处理(以及可能的终结器)。