`
emowuyi
  • 浏览: 1477773 次
文章分类
社区版块
存档分类
最新评论

Dispose、Close、=null三者之间的区别

 
阅读更多
上午想做个简单的单件设计模式(Singleton)的小例子,结果出现了一些意想不到的问题。我的本意是建立两个窗体类Form1和Form2,在Form2上放置一个名为Button1的按钮,单击Button1会调出Form1的窗口事例,并且保证再单击Button1的时候,不会再弹出第二个Form1实例,除非关掉Form1实例并重新单击Button1,总之,保证只能弹出一个Form1实例(当然不是用模态方式啦)。代码如下所示:
Form1类
public class Form1
{
private static Form1 frm;
private Form1()//这个构造函数只允许类内调用,所以是私有的
{
InitializeComponent();
}
public static Form1 CreateForm1()//该函数可带参数,自己想想如何实现
{
if(frm == null)
{
frm = new Form1();
return frm;
}
else
{
return frm;
}
}
}
Form2类
public class Form2
{
.....
private void button1_Click(object sender, System.EventArgs e)
{
Form1 frm1 = Form1.CreateForm1();
frm1.Show();
}
.....
}
于是问题出现了:我单击Form2窗体上的一个名为button1按钮要弹出Form1的窗口(函数如上),第一次可以弹出来,并且可以保证再单击button1时,不再弹出Form1的窗口,但是关闭Form1窗口实例后,再次单击button1按钮则出错,解释为无法访问名为“Form1”的已处置对象。这是什么原因?
经过细致的观察和向高手询问,终于搞清楚了问题的真相。这就是Dispose和null之间的区别。Dispose和Close是相同的,据说是因为有些类有Open的方法,所以为了对应才搞出了一个Close方法。Dispose()方法实际上是销毁了对象的实例,但是该对象变量仍然指向这块被销毁的内存地址上!而只要有所指向,它就绝不等于null!而若原来夫frm = new Form1();然后又frm = null;这意味着frm不再指向new出来的对象,他们之间的关系被“切断”了,frm成了一个没有指向的变量,但同时new出来的那个对象也占据着一块内存,它并没有被干掉!后来我又发现,窗体在执行Close()方法后会激发Closing事件,而使用dispose()方法则不会激发该事件。在singleton模式中,单例窗体的Closing事件里面,加入了“frm=null;”这么一句话,所以不要用dispose()关闭单例窗体,而要用Close()方法关闭。引申出来,所有拥有Close()方法的类,最好都用Close()方法关闭,而不要用Dispose()方法。
所以,上面的例子中,把frm1关掉后,它new出来的那个对象所占用的地址被dispose掉了,但是变量frm1仍然指向这块被dispose掉的地址!所以它也就不等于null!所以当再次单击Button1的时候,直接进入了else部分,导致了错误。那怎么解决呢?这么办,在Form1的Closed事件中将frm1设置成null,就可以了。因为关闭窗体,执行dispose的时候,窗体内的其他代码并不停止,直到执行完毕,所以,可以将frm1设置成null,完全没有问题。
这里还有另外一个问题。假如一个对象(自定义的类的实例)没有dispose掉,就把它设置成null,那这块内存怎么办呢?垃圾回收机制会自动收拾它的。但是垃圾回收机制,不能保证何时去回收它,所以你也不知道它到底啥时候能回收掉,这样可能影响系统的效率。解决方法是,使该类继承IDisposable接口,然后实现他的Dispose()方法。函数内写GC.SuppressFinalize(this);这样,如果手动调用dispose()方法,GC就不会通过析构函数再次销毁对象了。尤其当这个对象作为局部变量的时候,这样做是很有必要的。可以将dispose()写入finally{}语句中,更好的方法是使用using关键字把代码装入{}中。例如:
Using(Class1 cls1 = new Class())
{。。。。}
Using里的参数必须是实现了dispose方法的对象。当程序运行出{}时,自动销毁cls1(但是cls1!=null,这个已经反复说过多次了)。真正是实现的时候,可能还要考虑到多线程等诸多问题。
分享到:
评论

相关推荐

    探讨C#中Dispose方法与Close方法的区别详解

    (这里用using或许更好)当我们开发C#代码的时候,经常碰到一个问题,有些class提供Close(),有些class提供Dispose(),那么Dispose和Close到底有什么区别? 在这里,要明确一下C#程序(或者说.NET)中的资源。简单的...

    C#中Dispose和Close的区别

    首先,Dispose和Close基本上应该是一样的。Close是为了那些不熟悉Dispose的开发者设计的。因为基本上所有的developer都知道Close是干吗的(特别是对于那些有C++背景的developer)。

    C# oracle通用类

    = null) { throw new Exception("对象已经在另一个事务中"); } else { this._transaction = transaction.DataBaseTransaction; } } public void QuitTransaction() { if (this._transaction != null) {...

    asp.net sqlconnection con.close和con.dispose区别

    con.close() 是关闭连接,实际上是把连接放回ado.net的连接池,并没有真正关闭,所以再次连接时只是把连接... 您可能感兴趣的文章:C#基础:Dispose()、Close()、Finalize()的区别详解探讨C#中Dispose方法与Close方法的区别

    用C#写的 GPRS 连接管理程序

    Connection.ConnectManager cnnMan = null; try { cnnMan = new Connection.ConnectManager(); if (cnnMan.ConnectGPRS()) { cnnMan.Dispose(); cnnMan = null; Record1("拨号:CMWAP/CMNET"); return; } ...

    C#中析构函数、Dispose、Close方法的区别

    本文详细对比了C#中析构函数、Dispose和Close方法的区别,三者都是释放资源,本文介绍了他们各自的使用方法和使用场景,希望对大家有所帮助。

    房屋租赁系统

    dispose(); // TODO Auto-generated Event stub actionPerformed() } }); } return jButton1; } /** * This method initializes jButton2 * * @return javax.swing.JButton */ private JButton ...

    C#基础:Dispose()、Close()、Finalize()的区别详解

    .net内存回收与Dispose﹐Close﹐Finalize方法一. net的对象使用一般分为三种情况﹕1.创建对象2.使用对象3.释放对象二.创建对象1.创建对象实际分为两个步骤﹕变量类型宣告和初始化对象2.变量类型宣告(declare),如﹕ ...

    聊天系统计算机相关论文

    dispose(); System.exit(0); } } 事件2:处理按钮事件 public void actionPerformed(ActionEvent event) { Object source = event.getSource(); if (source == connectButton){ ...

    c#连接数据库常用的语句

    if (con == null) { //根据Web.Config文件中数据库连接串,建立数据连接 con = new SqlConnection(ConfigurationManager.ConnectionStrings["ApplicationServices"].ToString ()); } try { //判断连接对象...

    c++程序代码

    private System.ComponentModel.IContainer components = null; /// /// Clean up any resources being used. /// /// <param name="disposing">true if managed resources should be disposed; otherwise, ...

    c++课程设计

    private System.ComponentModel.IContainer components = null; /// /// Clean up any resources being used. /// /// <param name="disposing">true if managed resources should be disposed; otherwise, ...

    C#中标准Dispose模式的实现

    C#中标准Dispose模式的实现 C#中标准Dispose模式的实现 C#中标准Dispose模式的实现 C#中标准Dispose模式的实现 C#中标准Dispose模式的实现 C#中标准Dispose模式的实现 C#中标准Dispose模式的实现 C#中标准Dispose...

    c# dispose用法演示

    c#的dispose用法,相当于c++的析构函数

    GifDecoder

    * @return BufferedImage representation of frame, or null if n is invalid. */ public BufferedImage getFrame(int n) { BufferedImage im = null; if ((n >= 0) && (n < frameCount)) { im = (...

    Delphi new\dispose内存泄露问题解决方案

    delphi dispose释放结构体指针内存泄露解决方案 内存管理 delphi内存泄漏解决方案

    阿里巴巴SimpleImage图片压缩相关jar

    图片压缩,阿里巴巴SimpleImage 相关jar文件。其中包含依赖jar: commons-io-2.4.jar;... wr.dispose(); //释放simpleImage的内部资源 } catch (SimpleImageException ignore) { // skip ... } } } }

    C#实现的声音录制回放的小程序

    m_PlayEvent.Close(); if (m_HeaderDataHandle.IsAllocated) m_HeaderDataHandle.Free(); GC.SuppressFinalize(this); } public int Size { get { return m_Header.dwBufferLength; } } public IntPtr ...

Global site tag (gtag.js) - Google Analytics