问题描述
- C# 关于using代码块的疑问
-
关于using(){ } 代码块,我之前一直以为是在()中实例化的对象,在{}结束后就被释放,也就是被置为null。今天写了如下测试代码,却发现和我之前以为的不一样,求教,所谓的释放资源具体是指什么?using (form = new Form())
{
if (form != null)
Output("form in using");
}
Thread.Sleep(3000);
if (form != null)
{
Output("form out of using");
}
else
{
Output("form is null");
}输出:form in using form out of using
解决方案
using只是语法糖,它调用了dispose方法。
using (form = new Form())
{
if (form != null)
Output("form in using");
}
相当于
try
{
form = new Form();
if (form != null)
Output("form in using");
}
finally
{
form.Dispose();
}
这两段代码完全等价。
你看,没有任何地方把form设置为null
不过一旦调用过dispose,请不要再访问这个对象(尽管可以)
解决方案二:
再多说几句。
首先,C#是自动垃圾回收的,对象没有回收一说。只要你把对象的引用设置为null了,这个对象没有任何变量引用它,垃圾回收器会在合适的时候回收它。
因此,a = null不是回收的结果,而是回收的原因。因为不再引用,所以才回收,而不是回收了,a == null了。
至于为什么要dispose方法,以及简化它的调用而出现的语法糖using,那是因为C#本身不需要你去释放什么,但是如果你调用了非托管的资源。比如说你调用了一个C++写的dll,它分配了内存,那么你需要释放它。
基于windows api的winforms库,gdi库等等都存在一些非托管的内存。而且不光是内存,像打开的文件、数据库连接、网络连接等等也需要一个关闭的过程。因此你可以编写一个dispose方法, 放上这些逻辑,并且让调用者去调用。
注意,dispose方法本身没有什么特殊的,和别的方法一样,就是一个方法而已。原则上来说,dispose本身调用过后的对象,作为调用者,你不应该再访问它了。你可以看到,form也好,control也好,都有一个bool isdisposed,用来判断这个对象是否已经调用了dispose。
dispose之后,对象作为托管的对象,还是合法存在的,除非垃圾回收。