代码改变世界

.net托管代码和非托管代码的精要理解

2011-10-11 09:19  AnyKoro  阅读(490)  评论(0编辑  收藏  举报

托管代码:managed code

非托管代码:unmanaged code

在这里要理解一点,所有的代码都在.net framework里面,其中的代码本身没有托管不托管的概念。

直到,引入了CLR(Common Language Runtime)后,才有了托管或不托管的概念。

引入CLR的原因:编写C或C++时,我们都知道,需要对数组的边界要由考虑,否则会出现数组溢出的情况。这个问题,只是在软件开发中遇到的众多程序问题中的一个,其他的还有诸如没有正常释放等。为了能提高开发的效率,也提高程序的可靠性。那么就只有牺牲一部分的性能,来提出一个可以统一管理或监控的中间程序,该程序就是CLR。在这里微软也为这个CLR提供了一种语言,叫IL(中间语言),这个语言的提出最大的考虑是为程序提供更好的跨平台性。CLR在这里的作用,正如它的角色,主要负责垃圾收集,版本控制,线程管理等。这就构成了完整的.Net。

有了以上基础,托管和不托管也就明晰了,托管指的是把.net framework中的代码交给了CLR代为管理。非托管就是指没有交给CLR管理的那部分。

下面列举一些常用的非托管资源:AppliactionContext,Brush,Component,ComponentDesigner,Container,Context,Cursor,FileStream,Font,Icon,Image,Matrix,Object,OdbcDataReader,OleDBDataReader,Pen,Regex,Socket,StreamWriter,StreamReader,Timer,Tooltip等。

垃圾回收时自动运行的,但是有的时候垃圾回收无法及时或者全部删除过期数据。同时垃圾回收机制对于非托管代码也是无能为力的。

针对这种情况,我们有两个途径去手动完成“垃圾清理”工作:

1、声明一个析构函数,作为类的一个成员

这个方法是不推荐的,但是一般会作为一种安全保险的机制被引入,即用了方法2,然后再使用此方法确保一下。我们可以再析构函数中执行释放资源的工作,但是这么做事有局限的。由于垃圾回收器的运行规则导致了我们不能在析构函数中放置在特定时刻运行的代码(比如像要提前释放,不想等到快结束的时候释放)。但是如果对象占用了宝贵而重要的资源,就应该尽快释放,此时我们就引入了IDisposable接口

2、在类中实现System.IDisposable接口

该方法是推荐的。IDisposable接口有一个Dispose()方法,该方法用于显示释放由对象直接使用的所有未托管资源。与该Dispose()方法可以配合使用的是using,using确定了一个程序作用域,当超出该域时,Dispose()会被自动调用(注意不是Close())。如果在IL语言级别看生成的代码与try块一样。

using(ResourceGobbler instance=new ResourceGobbler())
{
   //.......Code
}

try
{
     ResourceGobbler instance=new ResourceGobbler()
     //......Code

finally
{
     instance.Dispose();

以上两个方法是等价的。

Close()方法有时候比Dispose() 从逻辑意义上来说更好,所以使用Close(),但是并没有替代Dispose(),只是在运行Close()的时候会自动运行Dispose()方法。在很多非托管类中很常见,比如DBConnection中

注:CLR与JRE时非常相像的,也正因此使得.net和java都具有跨平台性。只是.net一般不是用在非windows平台下。