如何处置托管资源的Dispose()方法在C#中的方法?方法、资源、Dispose

2023-09-04 00:24:07 作者:泪是无色的血

我知道处置()是用于非托管资源,并且当不再需要,而无需等待垃圾收集器以完成对象的资源,应设置。

不过,当处理的对象,它想喝垃圾收集器preSS定稿(GC.Sup pressFinalize(本);在code以下)。这意味着,如果该对象包括管理资源,我们将不得不采取的是照顾过,因为垃圾收集器将不会打扫一下。

在以下(从MSDN)的例子code,分量是一个管理的资源,我们调用Dispose()这个资源(component.Dispose())。我的问题是,我们如何实现此方法的组件类是管理资源?我们是否应该使用像收集()捅垃圾收集清理这一部分?

任何想法是AP preciated。谢谢你。

下面是code我看这是从MSDN:

 使用系统;
使用System.ComponentModel;

//下面的例子演示如何创建
//实现IDisposable接口资源类
//和IDisposable.Dispose方法。

公共类DisposeExample
{
//实现了IDisposable的基类。
//通过实施了IDisposable,你宣布
//这种类型的实例分配稀缺资源。
公共类MyResource:IDisposable的
{
    //指向一个外部非托管资源。
    私人IntPtr的手柄;
    //其他管理资源这一类使用。
    私人色差分量=新的组件();
    //轨道处置是否已调用。
    私人布尔处置= FALSE;

    //类的构造函数。
    公共MyResource(IntPtr的手柄)
    {
        this.handle =手柄;
    }

    //实现IDisposable。
    //不要使用此法虚拟的。
    //派生类不应该能够覆盖该方法。
    公共无效的Dispose()
    {
        处置(真);
        //这个对象将被Dispose方法来清理。
        //所以,你应该叫GC.Su pressFinalize到
        //借此对象从终结队列
        //和prevent定稿code此对象
        //从执行第二次。
        GC.Sup pressFinalize(本);
    }

    //的Dispose(BOOL处置)在两个不同的场景中执行。
    //如果要撤除等于true,该方法已被直接调用
    //或间接地由用户的code。托管和非托管资源
    //可以设置。
    //如果要撤除等于false,该方法被调用的
    从终结里面//运行时,你不应该引用
    //其他对象。只有非托管资源可以配置。
    私人无效的Dispose(BOOL处置)
    {
        //检查是否处置已被调用。
        如果(!this.disposed)
        {
            //如果要撤除等于true,处理所有管理
            //和非托管资源。
            如果(处置)
            {
                //处置管理的资源。
                component.Dispose();
            }

            //调用相应的方法进行清理
            //非托管资源在这里。
            //如果处置是假的,
            //仅执行以下code。
            CloseHandle的(处理);
            处理= IntPtr.Zero;

            //注配置之已经完成。
            处置= TRUE;

        }
    }

    //使用互操作调用所需的方法
    //清理非托管资源。
    [System.Runtime.InteropServices.DllImport(Kernel32中)]
    私有外部静态布尔CloseHandle的(IntPtr的手柄);

    //最后审定code使用C#析构函数的语法。
    //这个析构函数将运行仅当Dispose方法
    //不会被调用。
    //它给你的基类中的机会来完成。
    //不提供析构函数在从这个类派生的类型。
    〜MyResource()
    {
        //不要再在这里创建处置清理code。
        //调用Dispose(假)是最佳的方面
        //可读性和可维护性。
        处置(假);
    }
}
公共静态无效的主要()
{
    //将code这里创建
    //并使用MyResource对象。
}
}
 

解决方案   中国铁设2021届毕业生实习招聘,附职位列表

这意味着,如果该对象包括管理资源,我们将不得不采取的是照顾过,因为垃圾收集器将不会打扫一下。

这是错误的。垃圾收集器仍然会清理你的管理资源。终结也严格清理非托管资源,所以燮pressFinalize()调用不会伤害你。

既然你是新来的IDisposable模式,我会期待困惑你的下一个问题:编写终结。在C#中,你应该只在与一个完全新的非托管资源的处理写一个终结。所以,如果你有,例如,包装了System.Data.SqlClient.SqlConnection类型作为数据访问层的部分一类,你应该的没有的写终结该类型的,因为你仍然对付同一种潜在的非托管资源:SQL Server数据库的连接。终结该资源采取的护理已经由基本的SqlConnection类型。

在另一方面,如果你正在构建一个ADO.Net提供者一种全新的数据库引擎,你需要在你的连接类实现一个终结,因为从来没有做过的事情。

I know Dispose() is intended for unmanaged resource, and the resource should be disposed when it is no longer needed without waiting for the garbage collector to finalize the object.

However, when disposing the object, it suppress finalization of the garbage collector (GC.SuppressFinalize(this); in the code below). This means that if the object includes managed resource, we will have to take care of that too because garbage collector will not clean this up.

In the example code below (from MSDN), "Component" is a managed resource, and we call dispose() for this resource (component.Dispose()). My question is, how do we implement this method for Component class which is managed resource? Should we use something like Collect() to poke garbage collector to clean this portion?

Any idea would be appreciated. Thanks.

Below is the code I'm looking at which is from MSDN:

using System;
using System.ComponentModel;

// The following example demonstrates how to create
// a resource class that implements the IDisposable interface
// and the IDisposable.Dispose method.

public class DisposeExample
{
// A base class that implements IDisposable.
// By implementing IDisposable, you are announcing that
// instances of this type allocate scarce resources.
public class MyResource: IDisposable
{
    // Pointer to an external unmanaged resource.
    private IntPtr handle;
    // Other managed resource this class uses.
    private Component component = new Component();
    // Track whether Dispose has been called.
    private bool disposed = false;

    // The class constructor.
    public MyResource(IntPtr handle)
    {
        this.handle = handle;
    }

    // Implement IDisposable.
    // Do not make this method virtual.
    // A derived class should not be able to override this method.
    public void Dispose()
    {
        Dispose(true);
        // This object will be cleaned up by the Dispose method.
        // Therefore, you should call GC.SupressFinalize to
        // take this object off the finalization queue
        // and prevent finalization code for this object
        // from executing a second time.
        GC.SuppressFinalize(this);
    }

    // Dispose(bool disposing) executes in two distinct scenarios.
    // If disposing equals true, the method has been called directly
    // or indirectly by a user's code. Managed and unmanaged resources
    // can be disposed.
    // If disposing equals false, the method has been called by the
    // runtime from inside the finalizer and you should not reference
    // other objects. Only unmanaged resources can be disposed.
    private void Dispose(bool disposing)
    {
        // Check to see if Dispose has already been called.
        if(!this.disposed)
        {
            // If disposing equals true, dispose all managed
            // and unmanaged resources.
            if(disposing)
            {
                // Dispose managed resources.
                component.Dispose();
            }

            // Call the appropriate methods to clean up
            // unmanaged resources here.
            // If disposing is false,
            // only the following code is executed.
            CloseHandle(handle);
            handle = IntPtr.Zero;

            // Note disposing has been done.
            disposed = true;

        }
    }

    // Use interop to call the method necessary
    // to clean up the unmanaged resource.
    [System.Runtime.InteropServices.DllImport("Kernel32")]
    private extern static Boolean CloseHandle(IntPtr handle);

    // Use C# destructor syntax for finalization code.
    // This destructor will run only if the Dispose method
    // does not get called.
    // It gives your base class the opportunity to finalize.
    // Do not provide destructors in types derived from this class.
    ~MyResource()
    {
        // Do not re-create Dispose clean-up code here.
        // Calling Dispose(false) is optimal in terms of
        // readability and maintainability.
        Dispose(false);
    }
}
public static void Main()
{
    // Insert code here to create
    // and use the MyResource object.
}
}

解决方案

This means that if the object includes managed resource, we will have to take care of that too because garbage collector will not clean this up.

That is false. The garbage collector will still clean up your managed resources. Finalizers are also strictly for cleaning up unmanaged resources, and so the SuppressFinalize() call won't hurt you.

And since you are new to the IDisposable pattern I will anticipate your next point of confusion: writing finalizers. In C#, you should only write a finalizer when dealing with a completely new kind of unmanaged resource. So if you have, for example, a class that wraps the System.Data.SqlClient.SqlConnection type as part of a data access layer, you should not write a finalizer for that type because you're still dealing with the same kind of underlying unmanaged resource: sql server database connections. The finalizer for that resource is taken care of already by the base SqlConnection type.

On the other hand, if you're building an ADO.Net provider for a completely new kind of database engine you would need to implement a finalizer in your connection class because that has never been done before.