.NET Framework 的核心是其运行库执行环境,称为公共语言运行库(CLR)或.NET运行库。通常将在CLR控制下运行的代码称为托管代码(managed code)。
但是,在CLR执行编写好的源代码(使用CH或其他语言编写的代码)之前,需要编译它们。在.NET中,编译分为两个阶段:
(1)将源代码编译为Microsoft中间语言(IL)。
(2) CLR把L编译为平台专用的代码。
这个两阶段的编译过程非常重要,因为Microsoft中间语言是提供.NET 的许多优点的关键。Microsoft中间语言与Java字节码共享一种理念:它们都是低级语言,语法很简单(使用数字代码,而不是文本代码),可以非常快速地转换为本地机器码。对于代码,这种精心设计的通用语法有很重要的优点:平台无关性、提高性能和语言的互操作性。
前面对IL和 Java做了比较,实际上,IL比Java字节码的作用还要大。IL总是即时编译的(称为JIT编译),而 Java字节码常常是解释性的。Java的一个缺点是,在运行应用程序时,把Java字节码转换为内部可执行代码的过程会导致性能的损失。
JIT编译器并不是把整个应用程序一次编译完(这样会有很长的启动时间),而是只编译它调用的那部分代码(这是其名称由来)。代码编译过一次后,得到的本地可执行程序就存储起来,直到退出该应用程序为止,这样在下次运行这部分代码时,就不需要重新编译了。Microsoft认为这个过程要比一开始就编译整个应用程序代码的效率高得多,因为任何应用程序的大部分代码实际上并不是在每次运行期间都执行。使用JIT编译器,从来都不会编译这种代码。
通用类型系统CTS定义了可以在中间语言中使用的预定义数据类型,所有面向.NET Framework的语言都可以生成最终基于这些类型的编译代码。
CTS不仅指定了基本数据类型,还定义了一个内容丰富的类型层次结构,其中包含设计合理的位置,在这些位置上。代码允许定义它自己的类型。CTS的层次结构反映了中间语言的单一继承的面向对象方法。
公共语言规范(Common Language Specification CLS)和通用类型系统--起确保语言的互操作性。
CLS是一个最低标准集,所有面向.NET 的编译器都必须支持它。因为工是一种内涵非常丰富的语言,大多数编译器的编写人员有可能把给定编译器的功能限制为只支持L和CTS提供的一部分功能。只要编译器支持已在CLS中定义的内容,这就很不错。
(1)各个编译器的功能不必强大到支持.NET 的所有功能,这将鼓励人们为其他面向.NET的编程语言开发编译器。
(2)如果限制类只能使用CLS兼容的特性,就要保证用其他兼容语言编写的代码可以使用这个类。
这种方法的优点是使用CLS兼容特性的限制只适用于公共和受保护的类成员和公共类。在类的私有实现方式中,可以编写非CLS代码,因为其他程序集中的代码不能访问这部分代码。
垃圾回收器(garbage collector)用来在.NET中进行内存管理,特别是它可以恢复正在运行的应用程序需要的内存。到目前为止,Windows平台已经使用了两种技术来释放进程向系统动态请求的内存:
完全以手工方式使应用程序代码完成这些工作。· 让对象维护引用计数。
让应用程序代码负责释放内存是低级高性能的语言使用的技术,例如CH+。这种技术很有效,并且一般情况下可以让资源在不需要时就释放,但其最大的缺点是频繁出现错误。请求内存的代码还必须显式通知系统它什么时候不再需要该内存。但这是很容易被遗漏的,从而导致内存泄漏。
尽管现代的开发环境提供了帮助检测内存泄漏的工具,但它们很难跟踪错误,因为直到内存已大量泄漏,从而使Windows拒绝为进程提供资源时,它们才会发挥作用。到那个时候,由于对内存的需求很大,会使整个计算机变得相当慢。
.NET运行库采用的方法是垃圾回收器,这是一个程序,其目的是清理内存。方法是所有动态请求的内存都分配到堆上(所有的语言都是这样处理的,但在.NET 中,CLR维护它自己的托管堆,供.NET应用程序使用)。每隔一段时间,当.NET检测到给定进程的托管堆已满,需要清理时,就调用垃圾回收器。垃圾回收器处理目前代码中的所有变量,检查对存储在托管堆上的对象的引用,确定哪些对象可以从代码中访问——即哪些对象有引用。没有引用的对象就不再认为可以从代码中访问,因而被删除。Java就使用与此类似的垃圾回收系统。
之所以在.NET中使用垃圾回收器,是因为中间语言已用来处理进程。其规则要求,第一,不能引用已有的对象,除非复制已有的引用。第二,中间语言是类型安全的语言。在这里,其含义是如果存在对对象的任何引用,该引用中就有足够的信息来确定对象的类型。
垃圾回收机制不能和诸如非托管C++的语言一起使用,因为CH+允许指针自由地转换数据类型。垃圾回收的一个重要方面是它的不确定性。换言之,不能保证什么时候会调用垃圾回收器:CLR决定需要它时,就可以调用它。但可以重写这个过程,在代码中调用垃圾回收器。这在测试时很有帮助,但是在正常的程序中不应该这么做。
.NET很好地弥补了Windows提供的安全机制,因为它提供的安全机制是代码访问安全性(CodeAccess Security),而Windows仅提供了基于角色的安全性。
基于角色的安全性建立在运行进程的账户的身份基础上,换言之,就是谁拥有和运行进程。另一方面,代码访问安全性建立在代码实际执行的任务和代码的可信程度上。由于中间语言提供了强大的类型安全性,因此CLR可以在运行代码前检查它,以确定是否有需要的安全权限。.NET还提供了一种机制,使代码可以在运行前,预先指定需要什么安全权限。
基于代码的安全性非常重要,原因是它降低了与运行来历不明的代码有关的风险(如代码是从Internet上下载的)。即使代码运行在管理员账户下,也可以使用基于代码的安全性,指定这段代码不能执行管理员账户一般可以执行的某些类型的操作,例如读写环境变量、读写注册表或访问.NET反射特性。
应用程序域是分离组件的一种方式,它不会导致因在进程之间传送数据而产生的性能问题。其方法是把任何一个进程分解到多个应用程序域中。每个应用程序域大致对应一个应用程序,执行的每个线程都运行在一个具休的应用程序域中。
程序集是完全自描述性的,它是一个逻辑单元而不是物理单元,可以存储在多个文件中(动态程序集存储在内存中,而不是存储在文件中)。如果一个程序集存储在多个文件中,其中就会有一个包含入口点的主文件,该文件描述了程序集中的其他文件。
可执行代码和库代码使用相同的程序集结构。唯一的区别是可执行的程序集包含一个主程序入口点,而库程序集不包含。文章来源:https://www.toymoban.com/news/detail-452278.html
程序集的一个重要特征是它们包含的元数据描述了对应代码中定义的类型和方法。程序集也包含描述程序集本身的元数据,这种程序集元数据包含在一个称为“清单(manifest)”的区域中,可以检查程序集的版本及其完整性。文章来源地址https://www.toymoban.com/news/detail-452278.html
到了这里,关于C# 的编译与执行的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!