C#Dispose方法

时间:2009-06-09 18:22:24

标签: c# .net dispose

我在使用C#的'Dispose'模式时遇到了困难。我在这里有3个课程:管理类,表单和数据存储类。

管理类可以(如果需要)使用表单提示用户输入。表单从文件加载数据,然后用户可以修改该文件。在关闭时,表单必须保存此数据。数据存储类实现.Dispose(),它就是这样做 - 将更改写入磁盘。

由于此数据存储类(StoredInfo)是表单(MyForm)的成员,因此MyForm还必须实现.Dispose()以调用StoredInfo.Dispose。这就是给我带来问题的原因。我的管理类,在它的代码中:

Form.Dispose();
Form = null;

我的表格:

// As written by MSVS. The exception is OK - I just want this to get called.
#region IDisposable Members

public void IDisposable.Dispose()
{
    throw new NotImplementedException();
}

#endregion

...但是从不调用Form.Dispose()方法。步调调试器,执行:

Connector.Dispose() // The management class
    Form.Dispose()
Form.Dispose(bool disposing) // (1) Some method designer wrote?
    if (disposing && (components != null))
    {
        components.Dispose();
    }
    base.Dispose(disposing);
Connector.Dispose() // Back to the management class!
    Form = null;

我们以某种方式从未调用.Dispose,而是调用.Dispose(bool)。在C ++中,参数可以有默认值,我可以看到这一点,但在C#中,我迷失了。我最好的猜测是我的调试器没有告诉我实际发生了什么。

现在,查看类层次结构,我看到其他实现IDisposable的类 - 所以必须在某处有另一个Dispose()成员。它不是虚拟的,所以我不确定为什么我没有收到编译器错误。我尝试重写.Dispose(bool)方法,因为它被调用,虚拟,但是这样:

protected override void Dispose(bool disposing)
{
    StoredHosts.Dispose();
}

我得到“Type'ConnectorForm'已经定义了一个名为'Dispose'的成员,它具有相同的参数类型”,是的,我认为它确实...在Designer的代码中 。所以这不是一个选择。所以回到调用Dispose()。但是怎么样?我现在忽略了C ++析构函数的纯粹简单性和强大功能以及 determinism

4 个答案:

答案 0 :(得分:4)

Windows窗体向导会在您不应修改的代码周围添加特殊的“区域指令”,因此您可以根据需要修改Dispose内容,只要您保持在该模式中即可。

将IDisposable视为.NET做析构函数的方式。只要所有实现者都做对了,那么结果就等同于C ++析构函数(实际上C ++ / CLI从析构函数声明中生成Dispose方法,而且我很想念C#中的这个特性)。

请阅读以下背景信息:http://msdn.microsoft.com/en-us/magazine/cc163392.aspx

有几点需要注意。首先,disposing参数告诉你wat上下文正在调用Dispose(bool)虚拟方法。如果它是false,那么DO NOT DO ANYTHING!这意味着你被调用终结者线程。这几乎从来没有用过,这是这个模式设计的一个历史缺陷,因为它有99.99%有用的东西(确定性破坏逻辑)与只有0.01%有用的东西混合在一起(自定义自由线程完成原生资源)就好像它们一样是最好的朋友。

所以把你自己的清理代码放在if (disposing)分支中。

其次,请注意向导生成的代码在调用Dispose之前如何检查对象引用是否为非null。根据{{​​1}}的定义,您应该在同一个实例上无理由地多次调用IDisposable

所以你想这样做:

Dispose

答案 1 :(得分:2)

Form类(或者,确切地说,Component类)定义了自己的Dispose方法,该方法调用虚方法Dispose(bool disposing)

您需要将设计器生成的Dispose方法(覆盖虚拟方法并由Component.Dispose调用)移出Designer文件,然后将StoredHosts.Dispose();放入其中

答案 2 :(得分:1)

没有规则说你不能摆弄设计师的所作所为,只要你注意不要破坏它。随意添加到设计器的Dispose()方法,或删除它并在主源文件中写一个。

设计师并不神奇。它只写正常的C#。

答案 3 :(得分:0)

通过编写void IDisposable.Dispose(),您可以有效地告诉运行时调用该Dispose方法的特定版本,当且仅当该变量属于IDisposable类型时。

E.g。

Form f1 = new YourForm();
IDispoable f2 = new YourForm();

f1.Dispose(); //call to public void Dispose()
f2.Dispose(); //call to void IDisposable.Dispose()