C#处置方法

C#处置方法,c#,.net,dispose,C#,.net,Dispose,我对C#的“Dispose”模式有困难。我在这里有3个类:管理类、表单类和数据存储类 管理类可以(如果需要)使用表单提示用户输入。表单从文件加载数据,然后用户可以修改该文件。关闭时,表单必须将此数据保存回。数据存储类实现了.Dispose(),它只是将更改写入磁盘 由于此数据存储类(StoredInfo)是表单(MyForm)的成员,因此MyForm还必须实现.Dispose(),以便调用StoredInfo.Dispose。这就是给我带来问题的原因。我的管理类,在其代码中: Form.Disp

我对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();
}

我得到的“类型‘ConnectorForm’已经定义了一个名为‘Dispose’的成员,并且具有相同的参数类型”,是的,我想它确实。。。在设计者的代码中。所以这不是一个选择。现在回到调用Dispose()。但是怎么做呢?现在我忽略了C++析构函数的纯粹的简单性、力量和决定性。

< P>没有规则说你不能干涉设计师的工作,只要你注意不要打破它。可以随意添加到设计器的
Dispose()
方法,也可以删除它并在主源文件中写入一个


设计师不是魔术。它只写普通的C#。

表单类(或者确切地说,
组件
类)定义了自己的
Dispose
方法,该方法调用虚拟方法
Dispose(bool disposing)


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


Windows窗体向导在您不应该修改的代码周围放置了特殊的“区域指令”,因此您可以随意修改
Dispose
内容,只要您保持在模式内即可

将IDisposable视为.NET执行析构函数的方式。只要所有实现者都能得到正确的结果,结果就相当于C++析构函数(事实上C++ +CLI从析构函数声明中生成处理方法,而我深深地忽略了C语言中的特征)。 阅读本文了解一些背景知识:

有几件事需要注意。首先,
disposing
参数告诉您正在调用
Dispose(bool)
virtual方法的wat上下文。如果是
false
,则
不要做任何事情这意味着正在从终结器线程调用您。这几乎从来没有用过,这是这个模式设计中的一个历史缺陷,因为它有99.99%的有用性(确定性破坏逻辑)和0.01%的有用性(本地资源的自定义自由线程终结)混合在一起,就好像它们是最好的伙伴一样

因此,将自己的清理代码放入
if(disposing)
分支中

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

所以你想这样做:

if (Form != null)
{
    Form.Dispose();
    Form = null;
}

除了“不要用代码编辑器修改此方法的内容”之外,这是另一种方法。当我使用我的方法进行编辑时,设计师是否会破坏我的方法?但是,我发现您需要小心,因为设计师可能会决定覆盖您的更改。如果我最终更改了.designer文件中的某些内容,我会将其移动到.cs文件中,这样当设计器进行更多更改时,它会保留我所更改的内容;大多数情况下,它唯一真正需要处理的是InitializeComponents和与之相关的控件声明,并且您仍然可以修改InitializeComponents——它不会爆炸。我有时会将其更改为初始化控件,而不使用其默认构造函数。但是,如果您向其中添加了其他非常规格式的代码,则该代码可能会被设计器破坏。为什么不刷新关闭事件的数据?@unknown:您应该将其作为一个答案发布-我正在考虑。我在质疑在.Dispose()中执行磁盘I/O的合法性(因为Dispose有点像析构函数,所以不应该在析构函数中引发异常,而我正在做一些可能引发异常的事情。我必须问自己:如果表单剧烈终止(即异常终止)-我想保存数据吗?太好了!我只是用它来处理我的非设计器创建的对象。但是我将该方法从.designer.cs文件中移出,以便更好地实现它,以防设计器将其弄糟。
if (Form != null)
{
    Form.Dispose();
    Form = null;
}