topic 1:
c#是ms根据他的.net战略提出的一种新语言。根据微软的技术资料,他是一种c/c++语言的扩展和升级。那么他除了继承了c/c++的简洁优美的的语言之外
他还具有那些新特性呢?
交叉语言集成:我们知道com最大的优点就是实现了软件模块的功能和开发语言之间的独立性。那么在.net系统中依然沿袭了com的这个优点
自动内存管理:在c#出现之前java是唯一一个实现了自动内存管理的语 言,使java成为一种健壮的语言,但是由于自动内存管理,java也牺牲了很大一部分系统性能和编程的灵活性。c#借鉴了java的成功经验,而且在提高系统性能和编程灵活性上有着独到之处
交叉语言异常处理:在com中组件的出错处理是抛出令人迷惑的hresult和ole error.在.net中这种出错处理将有跨语言的异常处理来解决。
版本支持:取消了dll的版本混乱问题。
组件交互的简化模式:在com中vc,的调用com是比较繁琐的但是在vb中却异常简单。因此在.net中让c# ,c/c++,pascal等调用组件的方式统一化,简单化
topic 2:
c#具有如此多的功能,那么他们是如何实现的呢?这个问题回答有赖于对microsoft.net runtimes 技术:
微软中间语言(microsoft intermediate language, ab: msil):
这是一种微软定义的一种界于源代码和机器码之间的中间语言,并有特定的语言(如c# compiler:csc,vc complier:cl等)的编译器将其包装成exe格式的伪代码(p代码)。他和java的byte code无论在工作方式上还是框架结构上都有很大的不同。在这里你只需要记住:msil不是一种执行代码而是一种语言(你可以想象成是.net平台上的asm汇编语言)
元数据(metadata):
尽管il代码由编译器产生,但它并不是编译器提供给运行时仅有的东西。编译器同样产生有关你代码的元数据,它告诉运行时有关你代码的更多的东西,例如各种类型的定义、各种类型成员的签名以及其它数据。基本上,元数据是类型库、注册表内容和其它用于com的信息。尽管如此,元数据还是直接和执行代码合并在一起,并不处在隔离的位置。
il和元数据存放于扩展了pe格式的文件中(pe格式用于.exe和.dll文件)。当这样的一个pe文件被装载时,运行时从文件中定位和分离出元数据和il。
3.即时编译器(just �in-time compliers ,简称jiters)
c#和java的确很相像,但是他们之间最大的不同是java采用解释执行,而c#采用编译。但是c#的编译和c的编译又完全不同,他是一种jit编译(java也有,但是他们工作方式不同后面将会详细展开).
topic 3
由c#编译器生成的受管代码并不是原始代码,但它是中间语言(il)代码。这种il代码自身变成了ngws runtime的受管执行进程的入口。il代码明显的优势在于它是cpu无关的,这也意味着,你要用目标机器上的一个编译器才能把il代码转换成原始代码。
在进一步说明之前,我想给你已有的il指令的简短目录。尽管不需要你熟记和理解,但是它列出了你所必需的、c#程序所基于的知识基础这指明了msil将负责那些具体的事情。
算术和逻辑操作符
控制流
直接内存访问
堆栈操作
参数和局部变量
堆栈分配
对象模式
实例类型值
临界区
数组
分型位置
即时编译器(jitters)
topic4:
虽然il代码被包装在一个有效的pe文件中,但是你还是不能执行它,除非它被转换成为受管原始代码。这就是ngws runtime 即时编译器(也称作jitters)大显身手的时候。
为什么不把整个il pe文件编译成原始代码? 答案是时间--需要把il代码编译成cpu规格的代码的时间。这种编译将更加有效率,因为一些程序段从来就没有被执行过。例如,在我的字处理器中,邮件合并功能从来就没有被编译。
msil和jiter让我们联想起了java的byte code, jvm和jit。他们是如此的相像,但是我要告诉你的是这两者并不是如我们所想的那样相似反而他们有着天差地别的不同。
首先刚才我们说过msil可以理解为.net上的汇编语言。
这是因msil 不是一种可执行码仍然是一种某种形式的语言不过是编译的时候加上了metadata包装成了二进制流的格式,我们可以通过ms的ildasm反编译器查看到这种类似于汇编语言的中间码。而java的bytecode,从某种意义下它已经是一种可执行码了(不过不是cpu执行而是jvm执行).
c# 的jiter和 java的 jvm jit工作方式不同。
首先我们看一下.net的运行库和java的代码库的不同。在java中所有的系统库都以bytecode形式存放,然后由jvm解释程序中所有的需要用到得库代码然后调用本地系统的接口完成相应的操作。
而.net的通用运行库(clr)是100%本地代码。.net系统是一个
充满了clr的dll的大容器。当jit载入misl时,misl并不指
挥.net系统去调用本地的系统接口。而是指定.net系统去编译连接
那些需要的clr的dll。编译出来的是100%native code。从技术上
说,全部的处理过程如下:当一个类型被装载时,装载器创建一个存
根(stub),并使它连接每一个类型的方法。当一个方法第一次被调用
时,存根把控制交给jit。jit把il编译为原始代码,且把存根指针
指向缓冲了的原始代码。接着的调用将执行原始码。在某些位置上
(at some point),所有的il都被转换成为原始代码,而jitter处
于空闲状态。可以说c#是结合了c/c++编译和java的中间代码的
自的优点,又屏蔽了各自的缺点c/c++不独立平台,以及java的低
效率
c代码的编译过程 java代码解释过程 c# jit过程
java自己也有jit,但是它的jit是不彻底的。他人仍然不是100%的
native code,仍然需要jvm的解释执行。因此java的性能一直没有办法
提高。
c#的方法是编译但是又不同于c的编译,他将编译分为几个阶段来进行。
汇编代码的编译肯定比源代码来的快,jit的局部代码编译肯定比全部程
序编译来的快,因此使用c#编程性能上的损失比java少的多,当然和c
比起来还是有一点延迟特别是代码启动的时候,但是比java好得多了。
topic 5:
1 虚拟对象系统(vos)
到目前为止,你仅看到了ngws runtime如何工作,但是并不了解它工作的技术背景以及为什么它要这样工作。这节都是关于 ngws 虚拟对象系统的(vos)。
以下为在vos中形成声明、使用和管理类型模型时,ngws runtime的规则。在vos背后的思想是建立一个框架,在执行代码时不能牺牲性能,允许交叉语言集成和类型安全。
我提到的框架是运行时架构的基础。为了帮助你更好地了解它,我将它勾出四个区域。当开发c#应用程序和组件时,理解它们很重要。
1.1vos类型系统--提供丰富的类型系统,它打算支持全面编程语言的完全实施。
1.2元数据--描述和引用vos类型系统所定义的类型。元数据的永久格式与编程语言无关,但是,元数据拿自己当作一种互换机制(nterchange mechanism)来使用,这种互换是在在工具和ngws的虚拟执行系统之间。
1.3通用语言规范(cls)--cls定义了vos中类型的子集,也定义了常规的用法。如果一个类库遵守cls的规则,它确保类库可以在其它所有能实现cls的编程语言上使用。
1.4虚拟执行系统(ves)--这是vos实时的实现。ves负责装入和执行为ngws运得时编写的程序。
这四个部分一起组成了ngws runtime架构。每一部分在下面小节中描述。
1.1 vos类型系统
vos类型系统提供丰富的类型系统,它打算支持多种编程语言的完全实施。所以,vos必须都支持面向对象的语言和过程编程语言。
现在,存在着很多种近似但有点不兼容的类型。就拿整型当例子,在vb中,它是16位长,而在c++中,它是32位。还有更多的例子,特别是用在日期和时间以及数据库方面的数据类型。这种不兼容使应用程序的创建和维护不必要地复杂化,尤其当程序使用了多种编程语言时。
另一个问题是,因为编程语言之间存在着一些差别,你不能在一种语言中重用另一种语言创建的类型。(com用二进制标准接口部分地解决了这个问题)。 当今代码重用肯定是有限的。
发布应用程序的最大障碍是各种编程语言的对象模型不统一。几乎每一方面都存在着差异:事件、属性、永久保存(persistence)等等。
vos这里将改变 这种现象。vos定义了描述值的类型,并规定了类型的所有值所必须支持的一条合约。由于前面提到的支持面向对象和过程编程语言,就存在着两种值和对象。
对于值,类型存储于表述(representation)中,同样操作也在其中实行。对象更强大因为它显式地存于表述中。每一个对象都有一个区别于其它对象的识别号。
1.2元数据
尽管元数据用于描述和引用由vos类型系统定义的类型,但它还不能锁定到这个单个目标。当你写一个程序时,通过利用类型声明,你所声明的类型(假定它们是数值类型或引用类型)被告知给ngws runtime类型系统。类型声明存在于pe可执行文件内部的元数据中得到描述。
基本上,元数据用于各项任务:用于表示ngws runtime用途的信息,如定位和装载类、 内存中这些类的事例、解决调用 、翻译il为原始码、加强安全并设置运行时上下文边界。
你不必关心元数据的生成。元数据是由c#的"代码转il编译器"(code-to-il compiler,不是jit编译器)生成的。代码转il编译器发送二进制元数据信息给pe文件,是以标准的方式发送的,不象c++编译器那样,为出口函数创建它们自己的修饰名字。
你从元数据和可执行代码并存所获得的主要优势为,有关类型的信息同类型自身固定在一起,不会遍布很多地方。同样有助于解决存在于com中的版本问题。进一步地,你可以在相同的上下文中使用不同的版本库,因为库不仅被注册表引用,也被包含在可执行代码中的元数据引用。
1.3通用语言规范
通用语言规范(cls)并不是虚拟对象系统(vos)真正的一部分,它是特殊的。cls定义了vos中的一个类型子集,也定义了必须符合cls的常规用法。
那么,对此有什么迷惑呢?如果一个类库遵守cls规则,其它编程语言同样也遵守cls规则,那么其它编程语言的客户也可以使用类库。cls是关于语言的交互可操作性(interoperability)。因此,常规用法必须仅遵循外部可访问项目 (externally visible items)如方法、属性和事件等等。
我所描述的优点是你可以做以下工作。用c#写一个组件,在vb中派生它,因加在vb中的功能是如此之强大,在c#中再次从vb类派生它。只要所有的外部可访问项遵守cls规则,这样是可行的。
构建你的类库时要注意到cls协定。我提供了表2.1,用以给类型和外部可访问项定义协定规则。
这个清单不完整。它仅包含一些很重要的项目。我不指出出现在本书中每一种类型的cls协定,所以有个好主意:当你寻找cls协定时,至少应该用浏览该表,以了解哪种功能有效。不要担心你不熟悉这章表中的每一个含义,在这本书中你会学到它们。
表2.1 通能语言规范中的类型和功能
bool
char
byte
short
int
long
float
double
string
object(所有对象之母)
arrays(数组)
数组的维数必须是已知的(>=1),而且最小下标数必须为0。
要素类型必须是一个cls类型。
类型(types)
可以被抽象或隐藏。
零或更多的接口可以被实现。不同的接口允许拥有具有相同名字和签名的方法。
一个类型可以准确地从一个类型派生。允许成员被覆盖和被隐藏。
可以有零或更多的成员,它们是字段(fields)、方法、事件或者类型。
类型可以拥有零或更多个构造函数。
一种类型的可访问性可以是公共的或者对ngws组件来说是局部的;但是,仅公共成员可以认为是类型接口的一部分。
所有的值型必须从系统值型继承。异常是一个枚举--它必须从系统枚举(system enum)继承。
类型成员
类型成员允许隐藏或者覆盖另一种类型中的其它成员。
参数和返回值的类型都必须是 cls 协定 类型。
构造函数、方法和属性可以被重载。
一个类型可以有抽象成员,但仅当类型不被封装时。
方法
一种方法可以是静态、虚拟或者实例。
虚拟和实例方法可以是抽象的,或者是一个实现。静态方法必须总拥有一个实现。
虚拟方法可能是最后的(或者不是)。
字段(fields)
可以是静态或者是非静态。
静态字段可以被描述或只初始化。
属性
当获取和设置方法而不是使用属性语法时,属性可以公开。
获取的返回类型和设置方法的第一个参数必须是相同的cls类型--属性的类型。
属性名字必须不同,不同的属性类型用于区分是不充分的。
由于使用方法实现属性访问,如果 propertyname 是同一个类中定义的一个属性,你不能实现命名为 get_propertyname 和 set_propertyname 的方法。
属性可以被索引。
属性访问必须遵循这种命名格式:get_proname,set_propname。
枚举(enumerations)
强调类型必须是byte、short、int 或long。
每一个成员是一个枚举类型的静态描述字段。
一个枚举不能实现任何接口。
你允许给多字段设定相同的值。
一个枚举必须继承系统枚举(隐含在c#中)
异常
可以被引发和被捕获。
自定义异常必须继承系统异常。
接口
可需要实现其它接口。
一个接口可以定义属性、事件和虚拟方法。实现取决于派生类。
事件
增加和取消方法必须是都提供或者都没有 ,每一种方法采用一个参数,它是一个从系统代表元(system delegate)派生下来的类。
自定义属性
可以仅使用下更类型:type(类型),char, char, bool, byte, short, int, long, float, double, enum (一种cls 类型), and object.
代表元(delegates)
可以被创建和被激活
标识符(identifiers)
一个标识符的第一个字母必须来自一限制集。
通过大小写在单一范围内,不可能唯一地区别两个或更多个标识符(大小写不敏感)。
1.4虚拟执行系统(ves)
虚拟执行系统实现了虚拟对象系统。通过实现一个负责ngws runtime的执行引擎(execution engine,缩写ee)创建ves。这个执行引擎执行你用c#编写和编译的应用程序。
下列组件为ves的一部分。
1、中间语言(il)--被设计为很容易受各种各样的编译器所兼容 。在该框架之外,c++、vb和c#编译器都能够生成il。
2、装入受管代码--这包括解决内存中的名字、 表层类(laying out classes ),并且创建jit编译所必需的存根。通过执行经常性校验,包括加强一些访问规则,类装载器同样也增强了安全性。
3、用jit转换il成原始代码--il代码并不是设计成为一种传统的解释字节代码或树型代码,il转换是真正的编译。
4、装入元数据、校验类型安全和方法的完整性
5、垃圾收集(gc)和异常处理--两者都是基于堆栈格式的服务。受管代码允许你动态地跟踪堆栈。要动态地识别各个堆栈框架,jitter或其它编译器必须提供一个代码管理器。
6、描绘和查错服务--两者都取决于由源语言编译器所生成的信息。必须发出两个映射:一个映射从源语言结构发到指令流中的地址,一个映射从地址发到堆栈框架中的位置。当执行从il到原始代码的转换时,这些映射被重新计算。
7、管理线程和上下文,还有远程管理--ves为受管代码提供这些服务。
虽然这个清单并不完整,但它足以让你理解运行时基于的由ves提供的低层架构。
topic6:microsoft.net与java
.net和java都是为了asp而设计的方案,都希望在inte.net时代的asp上占有一席之地。孰优孰劣,现在还很难说.
ms的ceo ballmer接受电视采访中这样说过“我们相信xml所以设计了.net,而他们(指sun)相信java”
sun的ceo maclline在java发布的时候这样描述过java”你在你的网络计算机面前,你在文字处理软件上点选一下,就现在一个只有四个基本功能的文字处理软件。他们用心脏跳动以下的时间就穿过了来了,因为程序码很短。他又四个功能;删除,恢复,剪贴,打印。如果我需要文字向右对齐,我就可以下载额外的功能。如果我需要拼子检查我可以下载他。这就是一个子集:一种面向对象的,规模可调节的,结实的,可伸缩的环境”
客户端的小型化,应用服务化是未来的趋势,但是ms和sun的方式是如此的不同。
sun希望提供的是一个随处都可插拔的”软cpu”即jvm,跨平台,健壮性,是它的精华。java在嵌入式技术上的前景不错,sun已经在手机中值入他们的jvm,可以收发邮件玩三维游戏。但是java的梦想并不完全变为现实,java诞生快5年了可是我至今还没有用到那个听上去神乎其神的字处理软件,而且一个java的程序传道我机器上时我已经数不清我的心脏跳过多少下了。慢的离谱的速度,千奇百怪的配置环境,处处受限制的功能等等不能不让人怀疑它的前景。
ms呢?向来以软件漏洞百出,过于庞大的系统(2000庞大的令人难以相信)成为指责的对象。 如今ms也正在逐渐的摆脱原来windows包办一切的“母集”方式。逐渐走向客户端的移动化和可伸缩化。但是他们认为仍然需要
保持一个庞大的应用系统,但是不是在客户机上而是服务器端。
我们可以看到c#基本上实现了java大多数功能。但是唯一一个功能c#是相当弱的那就是跨平台。c#可不可以跨平台?当然可以,但是必须在另一个系统上实现另一套功能相同的clr和jit。也许在pc,小型机上可以做到。但是手持设备,手机上如何实现如此庞大的一个clr和jit呢?
因此c#是健壮的,面向对象的,可伸缩的,但是的跨平台方面要弱的多。但是ms认为xml可以弥补c#的不足。
ms的理想是这样的:在.net上实现vos,保证各种语言都能共享,其次保证
运行的健壮性。然后是在各种大型的服务器上都移植一套clr和jit.让在.net上运行的各种软件都获得跨平台的特性。在客户端,用户并不直接与.net打交道,而是通过xml,用xui处理gui界面,用soap调用.net服务上各种软件服务然后服务收费。
这就是.net和java,你认为将来我们会是一个什么样的世界呢?
Java Asp PHP .Net XML C/C++ CGI VB Jsp J2ee J2se J2me EJB Servlet Tomcat Resin Struts Weblogic Eclipse ANT GUI JMS Web servise IDEA Webphere Hibernate Spring Jboss Applet Swing Socket Javamail Perl Ajax P2P 安全 模式 框架 测试 开源 游戏
Windows XP Windows 2000 Windows 2003 Windows Me Windows 9.x Linux UNIX 注册表 操作系统 服务器 应用服务器