我已经阅读了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:
IDisposable.(在这种情况下,您需要IDisposable,但不需要实现终结器/析构函数.)IDisposable在我看来,部分混淆是它涵盖了相当多的用例,并且正确的实现会根据您正在做的事情而改变(即:包装本机资源,包装其他IDisposable类或使用Factored类型).为了解决这个问题,我在IDisposable上写了一个多部分系列 - 它可能有助于为你澄清一些.