C#和.NET没出生之前,Windows操作系统上的开发们常常使用COM编程模型:
COM,即Component Object Model,组件对象模型。允许个人构建可以由不同语言共享的代码库。
比如,Visual Basic开发者可以使用C++程序员构建的COM库(不是很理解,这个现在C#调用C++库有啥区别吗?)。
优点:语言无关
缺点:基础结构复杂、部署模型脆弱,只能部署在windows系统上。
1.1 .NET平台的主要优点
2002年正式发布了C#和.NET平台,当时主要是为了提供一种比COM更强大、更灵活、更简洁的编程模型(这三个都是针对COM模型的缺点而来的)。
1. 对已有代码具有完全的互操作性:已有的COM二进制组件可以和更新的.NET二进制组件共存(可以相互调用?),已有的.NET也可以和COM二进制组件共存。使用dynamic关键字可以进一步简化这种互操作性。
2. 支持多种编程语言:使用多种编程语言(C#、Visual Basic、F#等)创建.NET应用。
3. 所有支持.NET的语言共享的公共运行时引擎:这个引擎的一个特点是具有一组明确定义的类型,而每一种支持.NET的语言都能“明白”这些类型。(我所在的公司开发的产品就是C#和Lua相互调用,也不晓得是不是这个优点所说的)
4. 语言集成:.NET支持跨语言的继承、异常处理和代码调试。C#的基类可以在Visual Basic中进行扩展。
5. 全面的基础类库:这个库除隐藏了原始的API调用的复杂性外,还提供了所有被支持.NET的语言所使用的一致的对象模型。
6.简化的部署模型:与COM不同,.NET库不需要将二进制单元注册到系统注册表中。另外,.NET允许同一个*.dll的不同版本存在同一台机器上。(是放的路径不同呢还是加载的路径不同呢?之前遇到过产品线调用UI组件的时候调用了更低版本的PresentationFramework.dll,导致软件起不来,这也算一个问题吧,还是优点?)
1.2 .NET平台构造块(CLR、CTS和CLS)简介
使.NET成为现实的3个关键实体:
CLR、CTS和CLS。
程序员角度:.NET可以理解为一个运行库环境和一个全面的基础类库。
运行库层:
定义:CLR,即Common Language Runtime,公共语言运行库。
主要作用:定位、加载和管理.NET类型,也负责一些诸如内存管理、应用管托、处理线程、安全检查等底层细节的工作。
公共类型系统
定义:CTS,即Common Type System,公共类型系统。
主要作用:规范完整描述了运行库所支持的所有可能的数据类型和编程结构,指定实体间如何进行交互,也规定了它们在.NET元数据格式中的表示。
公共语言规范
一种特定的支持.NET的语言可能不支持CTS所定义的所有特性。
定义:CLS,Common Language Specification,公共语言规范。
主要作用:是一个相关规范,定义了一个让所有.NET语言都支持的公共类型和编程结构的子集。如果构造的.NET类型仅公开与CLS兼容的特性,那么可以肯定其他所有支持.NET语言都能使用它们。如果使用了与CLS不兼容的数据类型或编程结构,就不能保证所有的.NET语言能和你的.NET代码库交互。
这一大段给我的理解就是CTS指定了.NET平台所支持的数据类型和编程结构(啥是编程结构?是指顺序结构、选择结构和循环结构?),CLS是所有.NET语言所支持的公共类型和编程结构的子集,就好比广东人和河南人都是中国人(.NET平台),大家都讲普通话(CLS),但是广东人也可以讲粤语,河南人也可以讲河南话,但是大家要是一起交流,就只讲普通话,否则交流失败(无法与你的代码库交互)。
1.2.1 基础类库的作用
.NET平台提供一个适合用于全部的.NET程序语言的基础类库(BCL,Basic Class Library)。这个类库封装了各种基本类型,如线程、文件输入/输出(I/O)、图形绘制以及与各个外部硬件设备的交互,以及一些服务。
有个图,我这里没贴上来,大概就是基础类库提供了以下八种服务:
1. 数据库访问
2. GUI桌面API
3. 安全
4. 远程处理API
5. 线程
6. 文件输入/输出
7. Web API
8. 其他
CLR>CTS>CLS
1.2.2 C#的优点
C#的核心语法和JAVA语法很相似。然而不能说C#抄袭了JAVA(很不要脸啊)。
1. 不需要指针!(当然,需要时也是可以操作指针的,这个我没玩过,平常开发就没咋使用这个玩意儿)
2. 垃圾收集器能够自动管理内存。因此C#不支持delete关键字。(为了去掉delete这个众多程序员烦恼的东西,也是拼了)
3. 类、接口、结构、枚举和委托都有正式的语法结构。(难道哪种语言这些语法结构都是一个样的?)
4. 具有和C++类似的功能,可以简单的重载操作符为自定义类型。
5. 支持基于特性的编程。这种方式的开发允许我们注释类型及其成员来进一步限定其行为。[Obsolete]特性标记某种方法后,后面再使用这种方法的时候就会打印自定义的警告。
还有很多优点就不列了。很多优点都项目中都或多或少看到和用到过。
1.2.3 托管代码与非托管代码
C#生成的代码只能在.NET运行库中执行(你不能用C#来构建本机的COM服务器或者非托管的C/C++ API应用程序)。这种必须在.NET运行库下执行的代码称为托管代码。这些包含托管代码的二进制单元称为程序集(assembly)。也就是说不能直接在.NET上运行库承载的代码称为非托管代码。
1.3其他支持.NET的编程语言
安装Visual Studio时,我们会得到5种托管语言:C#、Visual Basic、C++/CLI、JavaScript和F#。相似像Smalltalk、Ruby、Python、COBOL和Pascal的.NET编译器等也是托管语言。
1.4 .NET程序集概览
.NET二进制文件不包括特定于平台的指令,它包含的是平台无关的IL(Intermediate Language,中间语言)和类型元数据。
这里有个图:
C#源代码 | C#编译器 | IL和元数据(.dll或.exe二进制文件) |
Perl .NET源代码 | Perl.NET编译器 | IL和元数据(.dll或.exe二进制文件) |
COBOL.NET | COBOL.NET编译器 | IL和元数据(.dll或.exe二进制文件) |
C++/CLI源代码 | C++/CLI编译器 | IL和元数据(.dll或.exe二进制文件) |
IL也称为MSIL或者CIL,微软中间语言或者公共中间语言,这三个都是指的同一个东西。
使用支持.NET的编译器生成dll或exe文件时,二进制大对象会被打包成一个程序集。程序集包含CIL代码,CIL代码类似java的字节码,因为它只在绝对必需的情况下才编译成特定平台的指令。(就是说我写的代码,就算不调用也不会被编译成CIL?好像也不对,那我编译成的组件,程序还没运行,怎么知道我的某些代码会不会被调用)。“必需绝对”通常指一段CIL指令被.NET运行库引用。程序集还包含元数据(metadata)。元数据详尽描述了二进制文件中的每个“类型”的特征。程序集本身也用元数据进行描述,名称叫做清单(manifest)。清单记录程序集的当前版本信息,文化信息(用于本地化字符串和图形资源)和正确执行所需的外部引用程序集的列表。
1.4.1 CIL的作用
将CalculatorExample编译成.exe文件后,通过Mocrosoft SDK提供的ildasm.exe工具,我们可以看到下面源程序的add函数被编译成的中间语言如图2所示。
using System;
namespace CalculatorExample
{
class Program
{
// 这个类包含应用程序的入口点
static void Main(string[] args)
{
Calc c = new Calc();
int ans = c.Add(10, 84);
Console.WriteLine("10 + 84 is {0}.", ans);
// 等待用户按Enter键来结束程序
Console.ReadKey();
}
}
// C#计算器
class Calc
{
public int Add(int x,int y)
{
return x + y;
}
}
}
图1
图2