1. CLR(Common Language Runtime,公共语言运行时(库))
可由多种.NET语言使用的运行时环境,其主要作用是定位、加载和管理.NET类型、内存管理、安全检查、线程管理等。.NET运行库提供了一个定义明确的运行库层,可以被支持.NET的所有语言和平台共享。
2. CTS(Common Type System,公共类型系统)
CTS是一个正式的规范,它规定了类型必须如何定义才能被CLR承载。CTS规范完整地描述了CLR所支持的所有数据类型和编程结构等,指定了这些实体之间如何交互,也规定了它们在.NET元数据中如何表示。通常只有那些设计.NET平台工具或者开发编译器的人才对CTS的内部工作非常关心,但是.NET编程人员都必须了解CTS中定义的常用类型主要有5种,以下是它们的简单介绍:
CTS类类型:
每一种.NET语言至少要支持class type的概念,这是OOP的基础。
CTS接口类型:
接口是抽象成员的集合,可以理解为一些约定,可以通过一个具体的类或结构来实现这些约定。就接口本身而言并没有什么用,因为没有任何实现,但是当用具体类去实现一个给定接口时,就可以通过接口引用来实现多态。C#种接口类型使用interface关键字来定义,通常.NET接口用大写字母I开头,且声明为public,如:
public interface IDraw
{
void Draw();
}
CTS结构类型:
.NET中的结构类型可以看成是具有值语义的轻量级类类型,适用于几何和数学数据。C#中用struct关键字创建结构类型:
struct Point
{
public int xPos, yPos; // 字段
public Point(int x, int y) // 构造函数
{
xPos = x; yPos = y;
}
public void ShowCurrentPos() // 方法
{
Console.WriteLine("({0}, {1})", xPos, yPos);
}
}
CTS枚举类型:
// 默认每一项用32位整数存储,但是可以改变存储大小,派生自System.Enum
enum Color
{
Red, // 默认从0开始,可以自定义值
Green,
Blue
}
CTS委托类型:
class Program
{
// 委托(delegate)在.NET中等效于类型安全的C/C++函数指针,但是.NET委托是派生自System.MulticastDelegate,而不是简单的指向原始内存地址的指针
delegate int BinaryOperate(int x, int y); // 该委托可以“指向”任意原型为带2个int参数并返回int的方法
static void Main(string[] args)
{
// 定义一个委托对象,指向一个Lambda
BinaryOperate addop = (int x, int y) => { return x + y; };
// 直接调用委托对象
int ret = addop(10, 88);
Console.WriteLine("ret = {0}", ret);
Console.ReadKey();
}
}
一个实体可以用委托向另一个实体传递调用,委托也是.NET事件的基础。
内建的CTS数据类型:
不同的语言用于声明内建CTS数据类型的关键字一般是不同的,但是所有语言的关键字最终都将解释成定义在mscorlib.dll程序集中的相同类型。下表是CTS内建数据类型,及它们在不同.NET语言中对应的关键字:
// 各种托管语言中的关键字只是System命名空间中真实类型的简化符号,可以通过语言关键字和正式的CTS类型来定义变量
int num1 = 0;
System.Int32 num2 = 0;
3. CLS(Common Language Specification,公共语言规范)
一种特定的.NET语言可能并不支持CTS所定义的全部特性,比如某些.NET语言可能不支持或支持指针类型。CLS是一套规则,描述了支持.NET的编译器必须支持的最小的和完全的特征集,以生成可由CLR承载的代码,同时可以被所有.NET语言用统一的方式进行访问。CLS可以看成是CTS所定义完整功能的一个子集。
CLS比较重要的一个规则是规则1:CLS规则仅约束程序集的public部分。
public class Calc
{
// public方法,不遵循CLS方法因为: 外部使用了无符号数不符合CLS约束(某些.NET语言不支持无符号数)
public uint Add(uint x, uint y)
{
return x + y;
}
// ok, 内部可以使用无符号数,只要对外public部分符合CLS即可
public int Sub(int x, int y)
{
uint tmpX = (uint)x, tmpY = (uint)y;
return (int)(tmpX - tmpY);
}
}
C#中可以使用特性来让编译器检查代码是否遵循CLS规则:
4. BCL(Base Class Library,基础类库)
由.NET平台提供的适用于全部.NET程序语言的基础类库,封装了各种基本类型如线程、文件IO、图形绘制、硬件交互及其他的运用服务等。
基础类库定义了一些可以创建任意类型软件运用程序的类型,如使用ASP.NET创建Web运用、使用WCF创建网络服务、使用Winows Form/WPF创建桌面GUI运用、使用ADO.NET与关系数据库交互、XML操作、文件系统交互等。
6. 程序集基本概念
C#编译生成的代码只能在.NET运行库中执行,这种必须在.NET运行库下执行的代码称为托管代码(managed code),包含这些托管代码的二进制单元称为程序集(assembly)。尽管.NET二进制文件与非托管的Windows二进制文件(*.dll *.exe)具有相同的文件扩展名,但是它们内部的结构是完全不同的。.NET二进制文件不包含特定于平台的指令,它包含的是平台无关的IL(Intermediate Language,中间语言,官方叫MSIL或CIL即Microsoft IL/Common IL,都是一个意思)和类型元数据。
当使用.NET编译器生成dll或exe文件时,二进制大对象(托管模块)会被打包成一个程序集。如:C#源代码——>1个或多个托管模块(包含IL、元数据等信息)+资源/数据文件——>合并成程序集(清单描述)。
程序集包含了IL代码、元数据,它本身使用清单进行描述,清单记录了程序集当前版本信息、文化信息、以及外部引用的程序集列表等。
7. IL的作用
Native Code Compilers编译生成的都是面向特定CPU架构(如x86,x64,ARM)的代码,但是面向CLR的编译器生成的都是IL代码,IL代码也称为托管代码,因为CLR会管理它的执行。C#编译器生成的是IL代码,并不是平台相关的指令,这一点适用于所有支持.NET的编译器。
使用IL反汇编器ildasm.exe打开一个C#程序集(编译生成的exe或dll文件),并查看一个类方法如下:
使用VB.Net编写一个同样的程序,再使用反汇编器查看其IL代码,发现是一样的:
.NET语言源代码不直接编译成特定于平台的指令,而是编译成IL代码的2个好处:1.语言的集成性,不同的.NET语言编译器生成几乎完全相同的IL指令能够让它们很好的进行交互;2.更好地实现平台无关性。
8. 将CIL编译成特定平台的指令
CIL(IL)指令并不是特定于平台的指令,CIL代码使用之前必须进行即时编译。将CIL代码编译成有意义的CPU机器指令的工具是CLR的JIT(just-in-time)编译器,也称为Jitter。CLR将针对各种不同CPU使用不同的JIT编译器,每个编译器都会针对底层平台进行优化。
当给定的JIT编译器将CIL指令编译成相应的机器代码时,它会用适合目标操作系统的方式将结果缓存在内存中,这样当一个方法被调用时,则它对应的CIL指令只在第一次调用时被编译成特定平台的指令并保留在内存中以备后续使用,因此以后的调用就不需要再次编译CIL了。
9. .NET类型元数据作用
元数据描述了每一个托管模块中定义的类型(如类、结构、枚举等)以及每个类型的成员(如字段、属性、方法、事件等)。且元数据总是与包含IL代码的文件关联,编译器同时生成元数据和IL代码,把两者绑定在一起并嵌入到最终生成的托管模块中,所以元数据和它描述的IL代码是同步的。
元数据是许多.NET技术的基础,这些技术包括WCF、反射、迟绑定、对象序列化、垃圾回收器等。
10. 程序集清单
.NET程序集也包含描述程序集自身的元数据,称为清单(manifest)。
11. 平台无关性
.NET的平台无关性是通过CLI(Common Language Infrastructure,公共语言基础设施)实现的。
原文地址:https://www.cnblogs.com/djh5520/p/14286801.html