多年来,Microsoft发布了多种技术来帮助开发者构造和实现代码。其中许多技术都提供了一定的抽象,允许开发者更多地思考如何解决他们的问题,更少地思考机器和操作系统本身。下面是一些例子:
·Microsoft基础类库(Microsoft Foundation Class library,MFC)在GUI(图形用户接)编程上方提供了一个C++抽象。使用MFC,开发者可以将精力集中在程序应该做的事情上,不用过多地关注消息循环、窗口过程、窗口类等。
·使用Microsoft Visual Basic 6以及更早的版本,开发者还能通过一个抽象更简单地构建GUI应用程序。这个抽象技术的宗旨与MFC相似,只是针对熟悉Basic语言的开发者进行了优化。另外,它对GUI编程的各个部分的侧重也有所不同。
·Microsoft的ASP(ActiveX服务系统网页)技术提供了一个抽象,允许开发者使用Visual Basic Script或者JScript来构建活动的、动态的网站。ASP允许开发者更多地关注网页内容,更少地关注网络通信。
·Microsoft的活动模板库(Active Template Library,ATL)提供了一个抽象,允许开发者更轻松地创建一些组件,以便由使用多种编程语言的开发者共享。
可以发现,每一种抽象技术的设计宗旨都是使开发者更容易将精力集中在一种特定的开发情形上,比如GUI应用程序开发、Web应用程序开发或者组件开发。如果一个开发者想要建立一个网站,该网站使用了一个组件,那么开发者必须学习多种抽象技术:ASP和ATL。除此之外,开发者必须精通多种编程语言,因为ASP需要Visual Basic Script或JScript,而ATL需要C++。所以,虽然这些抽象技术的目的是为我们提供帮助,但它们仍然要求开发者学习大量知识。而且经常遇到的问题是,多种抽象技术并不是从一开始便设计成相互协作的。所以,开发者还要解决集成问题。
Microsoft为.NET Framework制定的目标就是解决所有这些问题。可以看出,后文提到的每一种抽象技术都是为了简化特定的应用程序开发情形。Microsoft .NET Framework的目标不是为构建一种特定类型的应用程序的开发者提供一个抽象技术。相反,它的目标是为平台或者Microsoft Windows操作系统本身提供一个抽象技术。换言之,.NET Framework为所有类型的应用程序提升了抽象等级。这意味着开发者只需学习和掌握一个编程模型和一套API,不管开发者是用它们来构建控制台应用程序、图形应用程序、网站,还是构建由其他应用程序使用的组件。
.NET Framework的另一个目标是允许开发者使用自己选择的编程语言来工作。现在可以使用一种语言(比如Visual Basic或者Microsoft新推出的C#语言)来构建一个网站及其 组件。
单一的编程模型、API集合以及编程语言是抽象技术取得的重大进步,并极大地帮助了开发者。另一个好消息是,这些特点使集成问题不复存在,从而极大地增强了测试、部署、管理以及版本控制,并提高了代码的重用性,使开发者更容易重新规划其用途。我个人使用.NET Framework已经有几年时间,可以肯定地说,我再也不会回归到过时的抽象技术以及过时的软件开发方式。如果逼迫我那样做,那我情愿改行,因为那样只能引起我痛苦的回忆。事实上,当我回想起以前使用那些技术来进行的所有编程工作,我简直不敢相信我们这些程序员居然忍受了那么长的时间!
开发平台:.NET Framework
.NET Framework由两个部分构成:公共语言运行库(Common Language Runtime,CLR)和Framework类库(Framework Class Library,FCL)。CLR提供了所有类型的应用程序都要使用的编程模型。CLR包括它自己的文件加载器、内存管理器(垃圾收集器)、安全系统(代码访问安全性)、线程池等。除此之外,CLR还提供了一个面向对象的编程模型,它定义了类型和对象是什么,以及它们的行为方式。
Framework类库提供了所有应用程序模型都要使用的一个面向对象的API集合。利用其中包含的类型定义,开发者可以执行文件和网络I/O、调度其他线程上的任务、画图、比较字符串等。当然,所有这些类型定义都遵循CLR设定的编程模型。
Microsoft实际上发布了.NET Framework的三个版本:
·2002年发布的.NET Framework 1.0,包括Microsoft C#编译器的7.0版本。
·2003年发布的.NET Framework 1.1,包括Microsoft C#编译器的7.1版本。
·2005年发布的.NET Framework 2.0,包括Microsoft C#编译器的8.0版本。
本书完全围绕着.NET Framework 2.0和Microsoft C#编译器的8.0版本展开描述的。由于Microsoft在发布新版本的.NET Framework时,会尝试保持相当程度的向后兼容性,所以本书讨论的许多内容同样适用于早期版本。不过,我不会对早期版本特有的一些东西进行任何强调。
.NET Framework 2.0支持Windows的32位x86版本,以及Windows的64位x64和IA64版本。另外,还针对PDA(便携式数据编程)比如Windows和其他小型设备发布了.NET Framework的一个精简版本,名为.NET Compact Framework。2001年12月13日,欧洲计算机制造商联盟(European Computer Manufacturers Association,ECMA)接受了C#编程语言、一部分CLR以及一部分FCL作为其标准。因而形成的标准文档允许其他组织为其他CPU架构和其他操作系统构建这些技术的ECMA相容版本。实际上,本书相当多的内容是关于这些标准的。所以,假如想寻求符合ECMA标准的runtime/library实现,也能从本书获得相当多的帮助。不过,本书重点关注的还是Microsoft如何在台式机和服务器系统上实现这个标准。
Microsoft Windows Vista搭载了.NET Framework 2.0,但之前的Windows版本并没有这样做。要想在更早的Windows版本上运行.NET Framework应用程序,需要手工安装.NET Framework。幸运的是,Microsoft提供了一个.NET Framework重分发文件(redistribution file),并允许程序员随自己的应用程序一起自由地分发它。
相较于之前的任何Microsoft开发平台,.NET Framework允许开发者利用的技术多得多。尤其值得一提的是,.NET Framework真正强调了代码重用、代码专用、资源管理、多语言开发、安全性、部署以及管理的问题。在设计这个新平台时,Microsoft还认为有必要改善当前Windows平台的一些不足之处。下面列出的只是CLR和FCL提供的一小部分 内容。
.·一致的编程模型。以前常见的一种情况是,部分操作系统功能通过动态链接库(DLL)函数来访问,另一部分功能则通过COM对象来访问。现在,所有应用程序服务都通过一个通用的、面向对象的编程模型来提供。
·简化的编程模型。CLR旨在显著简化Win32和COM需要的管道连接(plumbing)工作以及一些晦涩难解的构造。特别指出的是,CLR现在能避免开发者必须理解以下任何一个概念:注册表、全局惟一标识符(GUID)、IUnknown、AddRef、Release、HRESULT等等。CLR并非只是将这些概念从开发者那里抽象出来。相反,所有这些概念在CLR中将不以任何形式而存在。当然,假如我们的.NET Framework应用程序需要与现有的非.NET代码进行互操作,那么仍然必须关注这些概念。
·一次能运行,一直能运行(Run once, run always)。所有Windows开发者都熟悉“DLL hell”这个版本控制问题。为一个新应用程序安装的组件覆盖了旧应用程序的组件,就可能发生DLL hell。它会造成旧的应用程序行为失常,或者完全“罢工”。现在,.NET Framework构架将应用程序组件完全隔离开,使应用程序总是加载当初生成和测试时使用的那些组件。如果一个应用程序在安装好之后能够运行,那么以后总是能运行,不会发生其组件被其他应用程序组件替换的问题。
·简化的部署。对于当今的Windows应用程序来说,它们的安装和部署实际并不方便。我们必须创建相应的文件、注册表设置和快捷方式。除此之外,完全卸载一个应用程序几乎是不可能的任务。Microsoft在Windows 2000中引入了一个新的安装引擎,它有助于解决所有这些问题。但是,一个公司在生成Microsoft Installer包时,仍然无法避免犯错。.NET Framework彻底解决了这些问题。.NET Framework组件不再通过注册表来引用。事实上,安装大多数.NET Framework应用程序时,只需将文件复制到一个目录,然后在“开始”菜单、桌面或者“快速启动”工具栏上添加一个快捷方式。卸载时,直接删除文件即可。
·广泛的平台支持。为.NET Framework编译源代码时,编译器生成的是通用中间语言(Common Intermediate Language,CIL)代码,而不是更为传统的CPU指令。在运行时,CLR会将CIL转换成本地CPU指令。由于向本地CPU指令的转换是在运行时完成的,所以这个转换是完全针对主机CPU进行的。换言之,我们可以在任何机器上部署.NET Framework应用程序,只要机器上正在运行符合ECMA标准的CLR和FCL版本。这些机器可以是x86、x64、IA64等。如果用户需要改换他们的计算机硬件或者操作系统,就会深刻体会到这种广泛的平台支持所带来好处。
·编程语言集成。COM允许不同的编程语言进行互操作。.NET Framework允许语言相互集成。这样一来,就可以自由使用其他语言的类型,感觉它们就像是我们自己的类型。例如,借助于CLR,针对用Visual Basic来实现的一个类,可以使用C++来创建它的一个派生类。CLR之所以允许这样做,是因为它定义并提供了一个“通用类型系统”(Common Type System,CTS)。面向CLR的所有编程语言都必须使用这个系统。“公共语言规范”(Common Language Specification,CLS)描述了编译器必须实现什么特性,才能使其对应的语言与其他语言良好地集成(CTS和CLS的中文译名采用的是Microsoft标准术语——译者注)。Microsoft自身提供了几个编译器来生成面向CLR的代码:C++/CLI,C#,Visual Basic .NET以及JScript。除此之外,其他一些公司和学术机构也提供了一些面向CLR的、用于其他语言的编译器。
·简化的代码重用。利用前面描述的机制,我们可以创建自己的类,为第三方应用程序提供服务。这极大地简化了代码重用,并为组件厂商打开了一个相当大的市场。
·自动内存管理(垃圾收集)。编程需要高超的技巧和严格的纪律,尤其是需要对资源的使用进行管理的时候,这些资源包括文件、内存、屏幕空间、网络连接、数据库资源等等。假如忘记释放其中的某个资源,最终会造成应用程序在无法预料的时间产生错误的行为。CLR能自动跟踪资源使用,保证应用程序永远不会造成资源泄漏。事实上,根本没有办法显式地“释放”内存。本书第20章将详细解释垃圾收集机制的工作原理。
·类型安全验证。CLR可以验证我们编写的所有代码都是类型安全的。类型安全性确保总是采取一致的方式来访问已分配的对象。所以,假如一个方法的输入参数声明为接受一个4字节的值,那么CLR会检测并捕捉到该方法打算将参数作为一个8字节值来访问。类似地,假如一个对象在内存中占用了10个字节,应用程序就不能强迫对象转换成允许读取10个以上的字节的形式。类型安全性还意味着执行流程只能经过已知的位置(也就是方法的入口)。不能构造一个任意引用,让它随便指向一个内存位置,并造成那个位置的代码开始执行。所有这些措施确保了类型安全性,将许多常见的编程错误和典型的安全漏洞(比如缓冲区溢出)消除于无形。
·丰富的调试支持。由于CLR同时面向多种编程语言,所以现在可以根据一项特定的任务来挑选最合适的语言,从而使用不同的语言来实现应用程序的不同部分。对于这种跨越了语言边界的应用程序,CLR提供了完全的调试支持。
·一致的方法出错行为。以前进行Windows编程时,让开发者特别苦恼的一个问题就是函数往往采取不一致的格式来报告错误。有的函数返回的是Win32状态码,有的函数返回的是HRESULT,有的函数则抛出异常。在CLR中,所有错误都是通过异常来报告的。使用异常,开发者可以将错误恢复代码与负责实际工作的代码隔离开。通过这种隔离,代码的编写、阅读和维护得到了显著的简化。除此之外,异常在工作时是跨越模块和语言边界的。另外,有别于状态码和HRESULT,异常是无法忽略的。CLR还提供了内建的堆栈辗转开解机制,能够更容易地定位任何bug和错误。
·安全性。传统的操作系统安全性允许根据用户账户来提供隔离和访问控制。这个模型经证明是行之有效的,但在其核心,已经假定所有代码都得到了同等的信任。如果全部代码都是从物理媒体(比如CD-ROM)或者可信的公司服务器上安装的,那么这个假定没有什么问题。但是,随着人们越来越多地依赖移动代码(比如Web脚本、从Internet上下载的的应用程序以及电子邮件附件等等),我们需要采取一种进一步以代码为中心的方式来控制应用程序的行为。代码访问安全性(code access security)为此提供了一个解决方案。
·互操作性。Microsoft知道开发者已经拥有数量相当大的现成代码和组件。要改写全部这些代码来充分利用.NET Framework平台,无疑是一项浩大的工程,而且可能妨碍人们快速采纳这一平台。所以,.NET Framework全面支持开发者访问现有的COM组件,并调用现有的DLL中的Win32函数。
用户虽然无法直接体验CLR及其强大的功能,但肯定会注意到利用了CLR的应用程序所具有的品质与功能。除此之外,由于CLR使应用程序能够更快地开发和部署,而且需要的管理量也少得多,所以用户和公司很快就会意识到CLR所带来的巨大优势。
开发环境:Microsoft Visual Studio
Visual Studio是Microsoft的开发环境。Microsoft多年来一直在经营它,现在进一步在其中集成了.NET Framework特有的许多东西。和任何好的开发环境一样,Visual Studio也包括以下各项:一个项目管理器;一个源代码编辑器;若干个UI设计器;大量向导、编译器、链接器、工具和实用程序;丰富的文档;调试器。可以用它为32位和64位Windows平台以及.NET Framework平台构建应用程序。另一个重要的增强是,现在所有编程语言和所有类型的应用程序都只需要一个集成开发环境。
Microsoft还提供了一个.NET Framework SDK。这个SDK中包括所有语言编译器、许多工具以及大量文档。利用这个SDK,可以在不使用Visual Studio的前提下为.NET Framework开发应用程序。为此,只需使用自己的编辑器和项目管理系统。但这样一来,无法实现Web窗体和Windows窗体的“拖放”式生成。我个人经常使用Visual Studio,本书也会时不地提到它。不过,本书主要侧重于.NET Framework和C#编程,所以不需要Visual Studio也能顺利地学习、使用和理解每一章所讲述的概念。
本 书 目 标
本书旨在解释如何为.NET Framework开发应用程序和可重用的类。这意味着我要解释CLR的工作原理及其提供的功能。另外,我还要讨论FCL的各个部分。没有任何一本书能够全面地解释FCL——其中包含数以千计的类型,而且这个数字正在以一个惊人的速度增长。所以,我准备将重点放在每个开发者都需要注意的核心类型上面。另外,虽然本书没有具体地讲述Windows窗体、XML Web服务、Web窗体等,但展示的技术同样适用于这些类型的所有应用程序。
虽然本书用C#来演示CLR的特性和访问FCL中的类型,但本书的目标不是教读者学习任何一种特定的编程语言。我相信,通过本书可以学到关于C#的大量知识,但教读者学会C#编程并不是本书的目标。除此之外,我假定读者已经熟悉了一些面向对象编程概念,比如数据抽象、继承和多态性。对这些概念的良好理解是至关重要的,因为CLR提供了一个面向对象编程模型,它的所有特性都是通过面向对象的方式揭示出来的。如果还不熟悉这些概念,强烈建议先找一本这方面的书来学习。
示例代码和系统需求
本书示例代码可从Wintellect.com下载。为了生成和运行示例,需要.NET Framework 2.0(和一个支持它的Windows版本)和.NET Framework SDK。
本书没有错误
虽然标题是这样说的,但我们都知道那是不可能的。审稿人、编辑以及我自己,都进行了艰苦的工作,希望能够提供最准确的、最新的、最深入的、版式美观的、容易理解的、没有bug的信息。但是,即使有这样一个完美的团队,但世事难料总是不可预料的。如果发现本书的任何错误(尤其是bug——也就是硬伤啦——译者注),请将相关信息发送给JeffreyR@Wintellect.com.
致 谢
没有许多人的帮助,我是不可能完成本书的。尤其要感谢下面这些人。
·我的家人 除了写作,其他方面所投入的时间和精力是无法衡量的。我只知道,没有Kristin(我的太太)和Aidan(我的儿子)的支持,根本不可能有这本书的面世。多少次,我们想花些时间一家人小聚,都因为本书而放弃。现在,本书总算告一段落,我们一家人终于有时间一起旅了。
·我的技术审校者和编辑 写作本书过程中,我真正得到一些“高人”的帮助。Christophe Nasarre在审计本书并确保我能以最恰当的方式来表达的过程中,表现出非凡的才能。他对本书的质量确实有着重要影响。与此同时,我还要特别感谢Jamie Haddock。Jamie读过本书的第1版,并向我发送过无数封电子邮件,提出改进意见。我保存了所有这些意见,然后请他在我写作本书第2版的过程中协助进行正式的审阅。Jamie对本书所做的贡献也具有深远意义。我还要感谢Stan Lippman和Clemens Szyperski,感谢他们的审校和我们曾经有过的热烈讨论。最后,我还要感谢Paul Mehner对本书提出的反馈意见。
·Microsoft Press编辑团队 与我联系最勤的Microsoft Press员工是Devon Musgrave和Joel Rosenthal。与他们合作非常愉快而顺利,他们尽力使我写的东西通顺流畅(这个句子除外?)。当然,我还要感谢Ben Ryan,我的组稿编辑,在履行整个合同期间,他一直为我“护航”。最后,还要感谢参与本书项目的其他Microsoft Press员工,他们是Kerri Devault,Elizabeth Hansford,Dan Latimer,Patricia Masserman,Bill Myers,Joel Panchot,Sandi Resnick和William Teel。
·Wintellect的员工 最后,我要感谢Wintellect大家庭中的每一个成员,在我写作本书的过程中,他们表现出极大的耐心。尤其要感谢Jim Bail,Jason Clark,Paula Daniels,Peter DeBetta,Sara Faatz,Todd Fine,Lewis Frazer, Dorothy McBay,Jeff Prosise,John Robbins和Justin Smith。
支 持
我们尽最大努力来保证本书的准确性。Microsoft Press通过以下网址为其出版的所有书籍提供勘误信息:
http://www.microsoft.com/mspress/support/
要想直接连接Microsoft Press Knowledge Base,并提出遇到的问题,请访问:
http://www.microsoft.com/mspress/support/search.asp
关于本书的任何意见、问题或想法,请通过以下途径发送给Microsoft Press。
邮政信箱:
Microsoft Press
Attn: CLR Via C# Editor
One Microsoft Way
Redmond, WA 98052-6399
电子邮件地址:
mspinput@microsoft.com
请注意,上述邮件地址并不提供产品支持。要获取有关C#、Visual Studio或者.NET Framework的支持信息,请访问Microsoft产品标准支持网站:
http://support.microsoft.com