C# 处理方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/971698/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C# Dispose method
提问by Thanatos
I'm having difficulty with C#'s 'Dispose' pattern. I have 3 classes at play here: A management class, a form, and a data-storage class.
我对 C# 的“处置”模式有困难。我在这里有 3 个类在起作用:一个管理类、一个表单和一个数据存储类。
The management class may (if it needs to) use the form to prompt the user for input. The form loads data from a file, which the user can then modify. As it is closed, the form must save this data back. The data-storage class implements .Dispose(), which does just that - writes the changes to disk.
管理类可以(如果需要)使用表单来提示用户输入。该表单从文件中加载数据,然后用户可以对其进行修改。当它关闭时,表单必须保存这些数据。数据存储类实现了 .Dispose(),它就是这样做的 - 将更改写入磁盘。
Since this data-storage class (StoredInfo) is a member of the form (MyForm), MyForm must then also implement .Dispose() so as to call StoredInfo.Dispose. This is what is giving me issues. My management class, in it's code does:
由于此数据存储类 (StoredInfo) 是表单 (MyForm) 的成员,因此 MyForm 还必须实现 .Dispose() 以便调用 StoredInfo.Dispose。这就是给我带来问题的原因。我的管理类,在它的代码中:
Form.Dispose();
Form = null;
And my form:
还有我的表格:
// 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
...yet the Form.Dispose() method is never called. Stepping with the debugger, execution goes:
...但从未调用 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;
We somehow never called .Dispose, but instead called .Dispose(bool). In C++, where arguments can have default values, I can see this, but in C#, I'm lost. My best guess is that my debugger is not showing me what is actually happening.
我们以某种方式从未调用过 .Dispose,而是调用了 .Dispose(bool)。在 C++ 中,参数可以有默认值,我可以看到这一点,但在 C# 中,我迷路了。我最好的猜测是我的调试器没有向我展示实际发生的事情。
Now, looking at the class hierarchy, I see other classes that implement IDisposable - so there must be another Dispose() member somewhere. It's not virtual, so I'm not sure why I'm not getting compiler errors. I tried overriding the .Dispose(bool) method, since that is getting called, and isvirtual, but with this:
现在,查看类层次结构,我看到其他实现 IDisposable 的类 - 因此某处必须有另一个 Dispose() 成员。它不是虚拟的,所以我不确定为什么我没有收到编译器错误。我尝试覆盖 .Dispose(bool) 方法,因为它正在被调用,并且是虚拟的,但是这样:
protected override void Dispose(bool disposing)
{
StoredHosts.Dispose();
}
I get "Type 'ConnectorForm' already defines a member called 'Dispose' with the same parameter types", which, yes, I suppose it does... in Designer's code. So that's not an option. So back to calling Dispose(). But how? I'm missing the sheer simplicity and power and determinismof C++ destructors at the moment.
我得到“类型'ConnectorForm'已经定义了一个名为'Dispose'的成员,具有相同的参数类型”,是的,我想它确实......在Designer的代码中。所以这不是一个选择。所以回到调用 Dispose()。但是如何?我现在正想念C++ 析构函数的绝对简单性、强大功能和确定性。
回答by mqp
There's no rule saying you can't fiddle with what the designer's done, as long as you're mindful not to break it. Feel free to add to the designer's Dispose()
method, or to remove it and write one in the main source file.
没有规则说你不能摆弄设计师所做的事情,只要你注意不要破坏它。随意添加到设计器的Dispose()
方法中,或者删除它并在主源文件中编写一个。
The designer isn't magic. It just writes normal C#.
设计师不是魔术师。它只是编写普通的 C#。
回答by SLaks
The Form
class (or, to be precise, the Component
class) defines its own Dispose
method, which calls the virtual method Dispose(bool disposing)
的Form
类(或,更确切地说,所述Component
类)定义它自己的Dispose
方法,它调用虚拟方法Dispose(bool disposing)
You need to move the designer-generated Dispose
method (which overrides the virtual method and is called by Component.Dispose
) out of the Designer file, and then put StoredHosts.Dispose();
inside of it.
您需要将设计器生成的Dispose
方法(覆盖虚拟方法并由 调用Component.Dispose
)移出设计器文件,然后放入StoredHosts.Dispose();
其中。
回答by Rune FS
by writing void IDisposable.Dispose() you effectively tells the runtime to call that particular version of the Dispose method if and only if the variable is of type IDisposable.
通过编写 void IDisposable.Dispose(),您可以有效地告诉运行时当且仅当变量是 IDisposable 类型时才调用该特定版本的 Dispose 方法。
E.g.
例如
Form f1 = new YourForm();
IDispoable f2 = new YourForm();
f1.Dispose(); //call to public void Dispose()
f2.Dispose(); //call to void IDisposable.Dispose()
回答by Daniel Earwicker
The Windows Form wizard puts special "region directives" around code that you're not supposed to modify, so you can modify the Dispose
stuff as much as you like, as long as you stay within the pattern.
Windows 窗体向导在您不应修改的代码周围放置了特殊的“区域指令”,因此您可以随意修改这些Dispose
内容,只要您保持在模式内即可。
Think of IDisposable as the .NET way of doing destructors. As long as all implementers get it right, then the result can be equivalent to C++ destructors (in fact C++/CLI generates the Dispose method from destructor declarations and I deeply miss that feature in C#).
将 IDisposable 视为执行析构函数的 .NET 方式。只要所有的实现者都做对了,那么结果就可以等同于 C++ 析构函数(实际上 C++/CLI 从析构函数声明生成 Dispose 方法,我非常怀念 C# 中的那个特性)。
Read this for some background: http://msdn.microsoft.com/en-us/magazine/cc163392.aspx
阅读本文了解一些背景:http: //msdn.microsoft.com/en-us/magazine/cc163392.aspx
There are a couple of things to be aware of. Firstly, the disposing
parameter tells you wat context the Dispose(bool)
virtual method is being called in. If it is false
, then DO NOT DO ANYTHING!
It means that you're being called from the finalizer thread. This is almost never useful and it's a historical flaw in the design of this pattern, because it has something 99.99% useful (deterministic destruction logic) mixed in with something only 0.01% useful (custom free-threaded finalization of native resources) as if they were best buddies.
有几件事需要注意。首先,该disposing
参数告诉您Dispose(bool)
正在调用虚方法的wat 上下文。如果是false
,则DO NOT DO ANYTHING!
表示您正在从终结器线程中调用。这几乎从来没有用,而且是这种模式设计中的一个历史缺陷,因为它混合了 99.99% 有用的东西(确定性破坏逻辑)和只有 0.01% 有用的东西(本地资源的自定义自由线程终结),就好像它们是最好的朋友。
So put your own cleanup code inside the if (disposing)
branch.
所以把你自己的清理代码放在if (disposing)
分支里。
Secondly, note how the wizard-generated code checks whether the object reference is non-null before calling Dispose
on it. According to the definition of IDisposable
, you should expect Dispose
to be called multiple times for no reason on the same instance.
其次,请注意向导生成的代码如何在调用对象引用之前检查对象引用是否为非空Dispose
。根据 的定义IDisposable
,您应该期望Dispose
在同一个实例上无缘无故地被多次调用。
So you want to do this:
所以你想这样做:
if (Form != null)
{
Form.Dispose();
Form = null;
}