【发布时间】:2011-03-24 20:04:44
【问题描述】:
我已经阅读了 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();
}
这是我的一次性课程:
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
}
结果是:
test 1a - 只是实例化 myclass,析构函数是 commentend,因为 myclass 不包含非托管资源:myclass.dispose 不会被调用,即使我关闭了应用程序(它的 dispose 被执行)。那么一旦我关闭应用程序,数据集的状态是什么?
test 1b - 取消注释析构函数,当我关闭应用程序时,所有的 dispose 都会被调用。
测试 2a 和 2b - 我只调用 gc.collect 进行上述测试:行为分别与测试 1a 和 1b 相同
测试 3 - 一切正常(当然)
很多帖子说,如果 myclass 不包含非托管资源,我不需要添加析构函数;然而在我的测试中,如果我不添加析构函数,当我关闭应用程序时 myclass.dispose 不会被调用。我还没有等待 gc 自己运行(如果我没记错的话 gc.collect 不保证类实例被释放)来检查它是否会调用 myclass.dispose 。 那么正确的实现是什么:总是定义 e 析构函数,或者如果 myclass 仅包含托管资源则避免它? 如果我填满了所有世代级别,在没有实现析构函数的情况下,是否会调用 myclass dispose 的 gc?
最后我注意到,如果我定义了一个析构函数,但不将该类声明为实现 IDisposable,那么处置链仍然有效。这可能是有道理的,因为析构函数可能会被转换为在 IL 中完成。但我发现它真的很令人困惑:它是某种我不知道的“隐式”接口实现吗? gc 可以处理该项目,但用户不能
提前谢谢你
斯特凡诺
【问题讨论】:
-
我只写过少数带有终结器的类(看起来像 C++ 析构函数的语法),这些类是用 C++/CLI 编写的,以实现与非托管 API 的互操作性。除非您与本机代码和资源进行大量互操作,否则您很少需要编写终结器。
-
@Brian:最常见的情况是间接处理资源,比如这里。
-
"如果我不添加析构函数,myclass.dispose 就不会被调用" - 但是析构函数使用 disposing=false 调用它,然后它什么都不做。走小路。仅当您直接处理非托管资源时,才使用析构函数(也称为终结器)。
-
@Henk:是的,你是对的。 :::删除他的评论以避免任何人可能不小心读到它并认为它是真的:::