仍然试图了解处置模式

2 c# dispose

我已经阅读了msdn以及有关处理模式的各种帖子,还有一些我不理解的事情.我编写了以下代码来测试dispose模式.请注意,没有无人管理的资源,我使用的是vs2008和.net 3.5:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void tryDispose()
    {
        //test 1 : allocate resource and leave manage it to gc
        BL.myclass df = new BL.myclass();
        //test 2 : try to force garbage collecting
        //GC.Collect();
       //test 3 : call dispose myself
       //using (BL.myclass df = new BL.myclass())
        //{ 

        //}

    }

    private void button1_Click(object sender, EventArgs e)
    {
        tryDispose();
    }
Run Code Online (Sandbox Code Playgroud)

这是我的一次性课程:

class myclass: IDisposable
{

    private StronglyTypedDs myDS;
    private bool _disposed;

    public myclass()
    {
        using (myDSTableAdapter docDocadpt = new myDSTableAdapter())
        {
            myDS = new StronglyTypedDs();
            docDocadpt.Fill(myDS.TheTable);
        }
    }


    #region IDisposable Members

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

    ~myclass()
    {
        Dispose(false);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (!_disposed)
        {
            if (disposing)
            {
                if (myDS != null)
                    myDS .Dispose();
                myDS = null;
            }
        }
        _disposed = true;
    }


    #endregion

}
Run Code Online (Sandbox Code Playgroud)

结果是:

测试1a - 只是实例化myclass,析构函数是命令,因为myclass不包含非托管资源:myclass.dispose未被调用,即使我关闭了应用程序(执行了其dispose).那么关闭应用程序后数据集的状态是什么?

测试1b - 取消注释析构函数,当我关闭应用程序时,可以调用所有处理.

测试2a和2b - 我只是调用gc.collect进行上述测试:行为分别与测试1a和1b相同

测试3 - 一切正常(当然)

很多帖子说,如果myclass不包含非托管资源,我不需要添加析构函数; 但在我的测试中,如果我不添加析构函数,当我关闭应用程序时,myclass.dispose不会被调用.我没有等待gc自己运行(如果我没记错gc.collect不保证类实例被解除分配)来检查它是否会调用myclass.dispose.那么正确的实现是什么:如果myclass只包含托管资源,总是定义e析构函数或者避免使用它?如果我填充了所有代的级别,那么在没有实现析构函数的情况下,是否会将gc称为myclass?

最后我注意到,如果我定义了一个析构函数,但是没有将该类声明为实现IDisposable,那么处置链无论如何都会工作.这可能是有意义的,因为析构函数可能被翻译为在IL中完成.但我发现它真的令人困惑:它是某种"隐式"接口实现我不知道?gc可以处理项目,但用户不能

先感谢您

斯特凡诺

Ree*_*sey 10

相信你的垃圾收集器.托管资源最终会得到清理.除非您有一些需要发布的外部资源,否则不需要终结器或实现IDisposable.

这通常意味着您只应在以下情况下实现IDisposable:

  1. 正在包装本机资源.(在这种情况下,您可能还需要终结器.)
  2. 正在封装一个实现的类IDisposable.(在这种情况下,您需要IDisposable,但不需要实现终结器/析构函数.)

IDisposable在我看来,部分混淆是它涵盖了相当多的用例,并且正确的实现会根据您正在做的事情而改变(即:包装本机资源,包装其他IDisposable类或使用Factored类型).为了解决这个问题,我在IDisposable上写了一个多部分系列 - 它可能有助于为你澄清一些.