哪怎么办? 自己写一个Dispose方法;去释放我们的内存

时间:2022-01-12 08:49:28

今天来谈谈C#的GC,也就是垃圾回收机制,非常的受教,总结如下
首先:谈谈托管,什么叫托管,我的理解就是奉求C#运行环境帮我们去打点,在这个运行环境中可以辅佐我们斥地内存和释放内存,斥地内存一般用new,内存是随机分配的,释放主要靠的是GC也就是垃圾回收机制。哪么有两个大问题 1.GC可以回收任何东西吗?2.GC什么时候来回收东西?回收那些东西?
对付第一个问题,GC可以回收任何东西吗?我是这样理解的,首先要大白一点,C#在强大也管不到非托管代码?哪么什么长短托管代码呢?好比stream(文件),connection(数据库连接),COM(组件)等等。。哪么这些东西是需要进行连接的,好比说我们写这样一句话FileStream fs = new FileStream(“d://a.txt”,FileMode.Open);实际上已经创建了和d://a.txt的连接,如果反复两次就会报错。哪么fs这个东西叫做非托管东西,也就是说C#

不能自动去释放和d://a.txt的连接。哪么对付非托管的代码怎么办,一会我来说。
    对付第二个问题,GC什么时候来回收,回收什么东西?我想后面的就不用我说了,固然是回收托管东西了。但是GC什么时候回收?是这样的:GC是随机的,没有人知道他什么时候来,哪么我写了一个例子,证明这一点
private void button1_Click(object sender, EventArgs e)

{           

AA a = new AA();

AA b = new AA();

AA c = new AA();

AA d = new AA();

}

public class AA{}

在讲这个例子之前,要大白什么被称之为垃圾,垃圾就是一个内存区域,没有被任何引用指向,或者不再会被用到。哪么在第一次点击按钮的时候会生成4个东西,第二次点击按钮的时候也会生成4个东西,但是第一次生成的4个东西就已经是垃圾了,因为,第一次生成的4个东西跟着button1_Click函数的结束而不会再被挪用(或者说不能再被挪用),哪么这个时候GC就会来回收吗?不是的!我说了GC是随机的,哪么你只管点你的,不一会GC就会来回收的(这里我们可以认为,内存中存在必然数量的垃圾之后,,GC会来),要证明GC来过我们把AA类改成
public class AA

{

~AA()

{

MessageBox.Show("析构函数被执行了");

}

}

要大白,GC清理垃圾,实际上是挪用析构函数,但是这些代码是托管代码(因为里面没有涉及到Steam,Connection等。。)所以在析构函数中,我们可以只写一个MsgBox来证明刚的想法;这个时候,运行你的措施,一直点击按钮,不一会就会呈现一大堆的“析构函数被执行了”…

好了,然后让我们看看能不能转变GC这种为所欲为的赋性,答案是可以的,我们可以通过挪用GC.Collect();来强制GC进行垃圾回收,哪么button1_Click改削如下
private void button1_Click(object sender, EventArgs e)

{           

AA a = new AA();

AA b = new AA();

AA c = new AA();

AA d = new AA();

GC.Collect();

}

哪么在点击第一次按钮的时候,生成四个东西,然后强制垃圾回收,这个时候,会回收吗?固然不会,因为,这四个东西还在执行中(要领还没结束),当点第二次按钮的时候,会呈现四次"析构函数被执行了",这是在释放第一次点击按钮的四个东西,然后以后每次点击城市呈现四次"析构函数被执行了",哪么最后一次的东西什么时候释放的,在*措施的时候释放(因为*措施要释放所有的内存)。
 

好了,此刻来谈谈非托管代码,适才说过,非托管代码不能由垃圾回收释放,我们把AA类改成如下
public class AA

{

FileStream fs = new FileStream("D://a.txt",FileMode.Open);

~AA()

{

MessageBox.Show("析构函数被执行了");

}

}

private void button1_Click(object sender, EventArgs e)

{

AA a = new AA();

}

如果是这样一种情况,哪么第二次点击的时候就会报错,原因是一个文件只能创建一个连接。哪么必然要释放失第一个资源,才可以进行第二次的连接。哪么首先我们想到用GC.Collect(),来强制释放闲置的资源,改削代码如下:
private void button1_Click(object sender, EventArgs e)

{

GC.Collect();

AA a = new AA();

}

哪么可以看到,第二次点按钮的时候,确实呈现了“析构函数被执行了“,但是措施仍然错了,原因前面我说过,因为Stream不是托管代码,所以C#不能帮我们回收,哪怎么办?
本身写一个Dispose要领;去释放我们的内存。代码如下:
public class AA:IDisposable

{

FileStream fs = new FileStream("D://a.txt",FileMode.Open);

~AA()

{

MessageBox.Show("析构函数被执行了");

}

#region IDisposable 成员
 

public void Dispose()

{

fs.Dispose();

MessageBox.Show("dispose执行了");

}

#endregion

}