C#托管代码、非托管代码及回收机制

网上找了下相关文字,发现一些很不错的,转过来,方便之后查看程序员

托管代码

  托管代码就是Visual Basic .NET和C#编译器编译出来的代码。编译器把代码编译成中间语言(IL),而不是能直接在你的电脑上运行的机器码。中间语言被封装在一个叫程序集(assembly)的文件中,程序集中包含了描述你所建立的类,方法和属性(例如安全需求)的全部元数据。你能够拷贝这个程序集到另外一台服务器上部署它。一般来讲,这个拷贝的动做就是部署流程中惟一的一个操做。编程

托管代码在公共语言运行库(CLR)中运行。这个运行库给你的运行代码提供各类各样的服务,一般来讲,他会加载和验证程序集,以此来保证中间语言的正确性。当某些方法被调用的时候,运行库把具体的方法编译成适合本地计算机运行的机械码,而后会把编译好的机械码缓存起来,以备下次调用(这就是即时编译)。随着程序集的运行,运行库会持续地提供各类服务,例如安全,内存管理,线程管理等等。这个程序被“托管”在运行库中。Visual Basic .NET和C#只能产生托管代码。若是你用这类语言写程序,那么所产生的代码就是托管代码。若是你愿意,Visual C++ .NET能够生成托管代码。当你建立一个项目的时候,选择名字是以.Managed开头的项目类型。例如.Managed C++ application。c#

非托管代码

  非托管代码就是在Visual Studio .NET 2002发布以前所建立的代码,例如Visual Basic 6, Visual C++ 6。 最糟糕的是,连那些依然残存在你的硬盘中、拥有超过15年历史的陈旧C编译器所产生的代码都是非托管代码。非托管代码直接编译成目标计算机的机械码,这些代码只能运行在编译出它们的计算机上,或者是其它相同处理器或者几乎同样处理器的计算机上。非托管代码不能享受一些运行库所提供的服务,例如安全和内存管理等。若是非托管代码须要进行内存管理等服务,就必须显式地调用操做系统的接口,一般来讲,它们会调用Windows SDK所提供的API来实现。就最近的状况来看,非托管程序会经过COM接口来获取操做系统服务。跟Visual Studio平台的其余编程语言不同,Visual C++能够建立非托管程序。当你建立一个项目,而且选择名字以MFC,ATL或者Win32开头的项目类型,那么这个项目所产生的就是非托管程序。缓存

总而言之,非托管代码是运行在公共语言运行库环境(CLR)的外部,由操做系统直接执行的代码。非托管代码必须提供本身的垃圾回收、类型检查、安全支持等服务;它与托管代码不一样,后者从公共语言运行库中得到这些服务。安全

二者区别

  对于Visual Basic和C#来讲,生活是简单的,由于你没有其它选择。当你在那些语言里面声明一个类,那么这个类的实例会在托管堆中被建立,垃圾收集器(GC)会帮咱们管理这些对象的回收。可是在Visual C++中,你有另外一个选择。即便你正建立一个托管程序,你能够决定哪些类是托管类型,哪些类是非托管类型的。服务器

非托管类型:app

class Foo
{
   private:

      int x;

   public:

      Foo(): x(0){}

      Foo(int xx): x(xx) {}
};

托管类型编程语言

_gc class Bar
{
  private:
      int x;
   public:
      Bar(): x(0){}
      Bar(int xx): x(xx) {}
};

他们惟一的区别就是类Bar的定义中有_gc关键字。这个关键字会给代码带来巨大的区别。函数

托管类型是能够被垃圾回收器所回收的。他们必需要用关键字new来建立,永远都不会在栈中出现。因此下面这行代码是合法的:spa

Foo f;//非托管类型

可是这一行代码就是非法的:

Bar b;//托管类型必须用new来建立

若是我在堆中建立一个Foo对象,那么我必需要负责清理这个对象:

Foo* pf = new Foo(2);
// . . .
delete pf;//手动清理

  C++编译器实际上会用两个堆,一个托管堆和一个非托管堆,而后经过对new操做符的重载来实现对建立不一样类型类的实例,分配不一样的内存。若是我在堆里面建立一个Bar实例,那么我能够忽略它。当没有其余代码在使用它的时候,垃圾回收器会自动清理这个类,释放其占用的资源。对于托管类型会有一些约束:它们不能实现多重继承,或者继承与非托管类型;它们不能用friend关键字来实现私有访问,它们不能实现拷贝构造函数。因此,你有可能不想把你的类声明为托管类型。可是这并不意味着你不想让你的代码成为托管代码。在Visual C++中,你能够选择。

托管代码的执行过程

  选择编译器:为得到公共语言运行库提供的优势,必须使用一个或多个针对运行库的语言编译器,如 Visual Basic、C#、Visual C++、JScript 或许多第三方编译器(如 Eiffel、Perl 或 COBOL 编译器)中的某一个。因为运行库是一个多语言执行环境,所以它支持各类数据类型和语言功能。您所用的语言编译器首先肯定可用的运行库功能,而后使用这些功能设计代码。编译器(而不是运行库)创建代码必须使用的语法。若是您的组件必须彻底可以被用其余语言编写的组件使用,您的组件的导出类型必须只公开公共语言规范 (CLS) 中包括的语言功能。

  编译,将源代码翻译为microsoft中间语言(MSIL)并生成所需的元数据。

  在执行时,实时 (JIT) 编译器将 MSIL 翻译为本机代码。在此编译过程当中,代码必须经过验证过程,该过程检查 MSIL 和元数据以查看是否能够将代码肯定为类型安全。

  运行代码:公共语言运行库提供使执行可以发生以及可在执行期间使用的各类服务的结构。

c# -- 对象销毁和垃圾回收

  有些对象须要显示地销毁代码来释放资源,好比打开的文件资源,锁,操做系统句柄和非托管对象。在.NET中,这就是所谓的对象销毁,它经过IDisposal接口来实现。再也不使用的对象所占用的内存管理,必须在某个时候回收;这个被称为无用单元收集的功能由CLR执行。

  对象销毁和垃圾回收的区别在于:对象销毁一般是明确的策动;而垃圾回收彻底是自动地。换句话说,程序员负责释放文件句柄,锁,以及操做系统资源;而CLR负责释放内存。

  C#处理销毁的一个备选方案--Finalizer及其模式。