C# 高级编程

所需积分/C币:9 2011-11-01 23:26:46 6.39MB PDF
9
收藏 收藏
举报

C# 高级编程 VS2008 C#高级编程第六版
121平台无关性 首先,这意味着包含字节代码指令的同一文件可以放在任一平台中,运行时编译过程的最后阶段 可以很容易完成,这样代码就可以运行在特定的平台上。换言之,编译为中间语言就可以获得NET 平台无关性,这与编译为Java字节代码就会得到Java平台无关性是一样的 注意NET的平台无关性目前只是一种可能,因为在编写木书时,NET只能用」 Windows平台, 但人们正在积极准备,使它可以用于其他平台(参见Mono项目,它用于实现NET的开放源代码,参 见htt:/ww.go- mono. conT/)。 1.22提高性能 前面把I和Java做了比较,实际上,IL比Java字节代码的作用还要大。I总是即时编译的(称 为J编译),而Java宇节代码常常是解释性的,Java的一个缺点是,在运行应用程序时,把Java字 节代码转换为内部可执行代码的过稈公导致性能的损失(但在最近,Jaa在某些平台上能进行JT编 译)。 JIT编详器并不是把整个应用程序一次编详完(这样会有很长的启动时间),而是只编详它调用的 那部分代码(这是其名称由来)。代码编译过一次后,得到的内部可执行代码就存储起来,直到退出该 应用程序为止,这样在下次运行这部分代码时,就不需要重新编译了。 Micros认为这个过程要比 开始就编译整个应用程序代码的效率高得多,因为任何应用程序的大部分代码实际上并不是在每次运 行过程中都执行。使用J编译器,从来都不会编译这种代码 这解释∫为什么托管L代码的执行几乎和內部机器代码的执行速度一样快,但是并没有说明为 什么 Microsd升t认为这会提高性能。其原因是编译过程的最后一部分是在运行时进行的,JT编译器确 切地知道程序运行在什么类型的处理器上,可以利用该处理器提供的任何特性或特定的机器代码指令 来优化最后的可执行代码。 传统的编译器会优化代码,但它们的优化过程是独立于代码所运行的特定处理器的。这是因为传 统的编详器是在发布软件之前编详为内部机器可执行的代码。即编译器不知道代码所运行的处理器类 型,例如该处理器是x86兼容处理器还是 Alpha处理器,这超出了基本操作的范。例如 Visual studi 6为般的奔腾机器进行了优化,所以它生成的代码就不能利用奔腾Ⅲ处埋器的硬件特性。相反 肛编译器不仅可以进行Ⅴ isual studio6所能完成的优化工作,还可以优化代码所运行的特定处理器。 123语言的互操作性 使用LL不仅支持肀台无关性,还支持语言的互操作性。简而言之,就是能将任何一种语言绵编详 为中间代码,编译好的代码可以与从其他语言编译过来的代码进行交互操作 那么除了C#之外,还有什么语言可以通过NET进行交互操作呢?下面就简要讨论其他常见语言 如何与NET交互操作 Visual basic 2008 Visual basic6在升级到Ⅴ isual Basic Net2002时,经历」一番脱胎换骨的变化,才集成到.NET Framework的第一版中, Visual basic语言对Ⅴ isual basic6进行了很大的演化,也就是说, Visual basic 6并不适合运行NET程序。例如,它与COM的高度集成,且只扣事件处理程序作为源代码显示给开 发人员,大多数后台代码不能用作源代码。另外,它不支持继承,Ⅴ isual basic使用的标准数据关型 也与NET不兼容 Visual basic6在2002年升级为Ⅴ /isual basic,NET,对Ⅴ Visual basic进行的改变非常大,完全可以 把ⅵ isual basic当作是一和新语言。现有的Ⅴ isual basic6代码不能编译为Ⅴ isual basic2008代码(或 Visual basic net2002、2003和2005代码),把 Visual basic6程序转换为Ⅴ isual basic2008时,需要 对代码进行大量的改动,但大多数修改工作都可以由 sual studio2008( Visual studio的升级版本,用 于与NET一起使用)自动完成。如果把 Visual basic6项目读到 Visual studio2008中, Visual studio2008 就会升级该项目,也就是说把Ⅴ isual basic6源代码重写为Ⅴ isual basic2008源代码。虽然这意味着其 中的工作已大大减轻,但用户仍需要检查新的ⅵ isual basic2008代码,以确保项目仍可正确工作,因 为这种转换并不|分完美。 这种语言升级的一个副作用是不能再把Ⅴ isual basic2008编译为内部可执行代码了。Ⅴ isual basic 2008只编译为中间语言,就像(#一样。如果需要继续使用 Visual basic6编写程序,就可以这么做, 但生成的可执行代码会完全忽略 NET Framework,如果继续把Ⅴ Visual studio作为开发环境,就需要安 装Ⅴ isual studio6。 2.Ⅴ isual C+-2008 Visual c+6有许多 Microsoft对 Windows的特定扩展。通过Ⅴ isual c++NET,又加入了更多的 扩展内容,来支持 NET Framework。现有的C艹源代码会继续编译为内部可执行代码,不会有修改, 但它会独立于NET运行库运行。如果让C++代码在 NET Framework中运行,就可以在代码的开头添 加下述命令 #using <mscorlib. dll> 还可以把标记传递给编译器,这样编译器假定要编译托管代码,因此会生成中间语言,而不 是内部机器码。C艹+的一个有趣的问题是在编译托管代码时,编译器可以生成包含内嵌本机可执行代 码的Ⅱ。这表小在C艹+代码中可以把托管类型和非托管类型合并起来,因此托管C++代码: class my class 定义了一个普通的C++类,而代码: ref class Myclass 生成了一个托管类,就好像使用C#或Ⅴ isual basic2008编写类一样。实际上,托管C→+比C更 优越的一点是可以在托管C++代码中调用非托管C++类,而不必采用COM交互功能。 如果在托管类型上试图使用NET不支持的特性(例如,模板或类的多继承),编译器就会出现一个 错误。另外,在使用托管类吋,还需要使用非标准的C++特性。 因为C艹+允许低级指针操作,C艹+编译器不能生成可以通过CLR内存类型安全测试的代码。如 果CLR把代码标识为内存类型安全是非常重要的,就需要用其他一些语言编写源代码,例如C#或 Visual basic2008。 3.COM和COM+ 从技术上讲,COM和COM+并不是面向NEr的技术,因为基于它们的组件不能编译为(但如 果原来的COM组件是用C+-编写的,使用托管C++,在某种程度上可以这么做)。但是,COM+仍然 是一个重要的工具,因为其特性没有在NET中完全实现。另外,COM组件仍可以使用-NET集成了 COM的互操作性,从而使托管代码可以调用COM组件,COM组件也可以调用托管代码(见第24章) 在一般情况下,把新组件编写为、NET组件,人多是为了方便,因为这样可以利用.NET基类和托管代 码的其他优点。 13中间语言 如前所述, Microsoft中间语言显然在 NET Framework中有非常重要的作用。C#开发人员应明自 C#代码在执行前要编译为中间语言(实际上,C#编详器仅绵译为托管代码),这是有意义的,现在应详 细讨论一下IL的主要特征,因为面向NET的所有语言在逻辑上都需要支持IL的上要特征。 下面就是中间语言的主要特征 面向对象和使用接口 值类型和引用类型之间的巨大差别 ●强数据类型 使用异常来处理错误 使用特性( attribute 下面详细讨论这些特征 131面向对象和接口的支持 NEI的语言无关性还有一些实际的限制。中间语言在设计时就打算实现某些特殊的编程方法 这表小血向它的语言必縯与编程方法兼容, Microsoft为Ⅱ选择的特定道路是传统的血向对象的编程, 带有类的单一继承性。 注意 不熟悉面向对象概念的读者应参考附录B,获得更多的信息。 除了传统的面向对象编程外,中间语言还引入了接口的概念,它们显示了在带有COM的 Windows 下的第一个实现方式。NET接口与COM接口不同,它们不需要支持任何COM基础结构,例如,它 们不是派生自 IUnknown,也没有对应的GUID。但它们与COM接口共享下述理念:提供一个契约, 实现给定接口的类必须提供该接口指定的方法和属性的实现方式。 前面介绍了使用NET意味着要编译为中间语言,即需要使用传统的面向对象的方法来编稈。但 这并不能提供语言的互操作性。毕竟,CH和Java都使用相同的面向对象的范型,但它们仍不是可交 互操作的语言。下面需要详细探讨一下语言互操作性的概念。 首先,需要确定一下语言互操作性的含义。毕竞,COM允许以不冋语言编写的组件一起工作, 即可以调用彼此的方法。这就足够了吗?COM是个二进制标准,允许组件实例化其他组件,调用 它们的方法或属性,而无须考虑编写相关组件的语言。但为了实现这个功能,每个对象都必须通过 COM运行库来实例化,通过接口来访问。根据相关组件的线程模型,不同线程上内存空间和运行组 件之间要编组数据,这还可能造成很大的性能损失。在极端情况卜,组件保存为可执行文件,而不是 DLL文件,还必须创建单独的进程来运行它们。重要的是组件要能与其他组件通信,但仅通过COM 运行库进行通信。无论COM是用于允许使用不同语言的组件直接彼此通信,或者创建彼此的实例, 系统都把COM作为中间件来处理。不仅如此,COM结构还不允许利用继承实现,即它丧失了面向 对象编程的诈多优势。 个相关的问题是,在调试时,仍必须单独调试用不同语言编写的组件。这样就不可能在调试器 上调试不同语言的代码了。语言互操作性的真正含义是用一种语言编写的类应能直接与用另一种语言 编写的类通信。特别是: ●用一种语言编写的类应能继承用另一种语言编写的类。 个类应能包含另一个类的实例,而不管它们是使用什么语言编写的 个对黎应能直接调用用其他语言编写的另一个对象的方法。 ●对象(或对象的引用)应能在方法之间传递 ●在不同的语言之间调用方法时,应能在调试器中调试这些方法调用,即调试不同语言编写的 源代码。 这是一个雄心勃勃的目标,但令人惊讶的是,NET和中间语言已经实现了这个目标。在调试器 上凋试方法吋, Visual' Studio ide提供了这样的具(不是CLR提供的)。 13,2相异值类型和引用类型 与其他编程语言·样,中间语言提供了许多预定义的基本数据类型。它的·个特性是值类型和引 用类型有明显的区别。对于值类型,变量直接保存其数据,而对于引用类型,变量仅保存地址,对应 的数据可以在该地址中找到。 在C++中,引用类型类似于通过指针来访问变量,而在Ⅴ visual basic中,与引用类型最相似的是 对象, Visual basic6总是通过引用来访问对象。中间语言也有数据有储的规范:引用类型的实例总是 存储在一个名为"托管堆"的内存区域中,值类型一般存储在堆栈中(但如果值类型在引用类型中声明为 字段,它们就内联存储在堆中)。第2章"C#基础"讨论堆栈和堆,及其工作原理 133强数据类型 中间语言的一个重要方面是它基于强数据类型。所有的变量都清晰地标记为属」某个特定数据类 (在中间语言中没有Ⅴ Visual basic和脚本语言中的 Variant数据类型)。特别是中间语言一般不允许对 模糊的数据类型执行任何操作。 例如, Visual basic6开发人员习惯于传递变量,而无需考虑它们的类型,因为Ⅴ isual basic6会 自动进行所需的类型转换。C艹+开发人员习惯于在不同类型之间转换指针类型。执行这类操作将大大 提高性能,但破坏∫类型的安全性。因此,这类操作只能在某些编译为托管代砢的语言中的特殊情况 下进行。确实,指针(相对于引用)只能在标记了的C代码块中使用,但在ⅵ sual basic中不能使用(但 般在托管C—中允许使用)。在代码中使用指针会立即导致CLR提供的内存类型安全性检查失败 注意,一些与NET兼容的语言,例如Ⅴ isual basic2008,在类型化方面的要求仍比较松,但这是 可以的,因为编译器在后台确保在生成的L上强制类型安全。 尽管强迫实现类型的安仝性最初会降低性能,但在许多情况下,我们从NET提供的、依赖于类 型安全的服务中获得的好处更多。这些服务包括 语言的互操作性 垃圾收集 安全性 ●应用程序域 下面讨论强数据类型化对这些NFT特性非常重要的原因 1.语言互操作性中强数据类型的重要性 如果类派生自其他类,或包含其他炎的实例,它訫需要知道其他类使用的所有数据类型,这就是 强数据类型非常重要的原因。实际上,过去没有任何系统指定这些信息,从而成为话言继承和交互操 作的真止障得。这类信息不只是在一个标准的可执行文件或DLL中出现。 假定将Ⅴ isual Basic2008类中的一个方法定义为返回一个 Integer-- Visual basic2008可以使用的标 准数据类型之·。但C#没有该名称的数据类型。显然,我们只能从该类中派生,再使用这个方法 如果编译器知道如何把Ⅴ isual Basic2008的 Integer类型映射为C#定义的某种已知类型,就可以在C井 代码中使用返回的类型。这个问题在NET中是如何解决的? (1)通用类型系统(CTS) 这个数据类垩问题在NET中使用通用类型系统(CTS)得到了解决。CTS定义了可以在中间语言中 使用的预定义数据类型,所有面向 NET Framework的语言都可以生成最终基于这些类型的编译代码 例如, Visual basic2008的 Integer实际上是一个32位有符号的整数,它实际映射为中间语言类 型int32。因此在中间语言代码中就指定这种数据类型。C#编译器可以使用这种类型,所以就不会有 问题了。在源代码中,CH用关键字in来表示ln32,所以编译器就认为Ⅴ isual basic2008方法返回一 个int类型的值。 通用类型系统不仅指定了基本数据类型,还定义了一个内容丰富的类型层次结构,其中包含设计 合理的位置,在这些位置上,代码允许定义它自己的类型。通用类型系统的层次结构反映∫中间语言 的单一继承的面向对象方法,如图1-1所示 引用类型 楼囗类型 值炎 用户定义 橡什炎型 自我描述类型 内置值袭型 的粪型 枚 炎荛型 数 要托 装的值类型 用户定义的 引用类型 图1-1 这个树形结构中的类型说明如表1-1所示。 表1-1 义 T 代表任何类型的基类 Value type 代表任何值类型的基类 Reference Types 通过引用来访问,且存储在堆中的任何数据类型 Built-in Value Types 包含大多数标准基本类型,可以表小数字、 Boolean值 或字符 Enumerations 枚举值的集合 User-defined alue 在源代码中定义,且保存为值类型的数据类型。在C es 它衣示结构 Interface Types 接 Pointer Iypes 指针 Self-describing Types 为垃圾回收器提供信息的数据类型(参见下一节) Arrays 包含对象数组的类型 Class Typcs 可自我描述的类型,但不是数组 Delegates 用于把引用包含在方法中的类型 User-definedReference 在源代码中定乂,且保存为引用类型的数据类型。在C T 中,它衣示类 Boxed Value Types 值类型,临时打包放在一个引用中,以便于存储在堆中 这里没有列出内置的所有值类型,因为第3章将详细介绍它们。在C#中,编译器识别的每个预 定义类型都映射为一个Ⅱ内置类型。这与 Visual basic2008是一样的。 (2)公共语言规范(CIS) 公共语言规范( Common Language Specification,CLS)和通用类型系统·起确保语言的互操作性。 CLS是一个最低标准集,所有面向NET的编译器都必须支持它。因为Ⅱ是一种内涵非常丰富的语言 大多数编译器的编写人员有可能把给定编译器的功能限制为只支持Ⅱ和CLS提供的一部分特性。只 要编译器支持凵在CLS中定义的内容,这就是很不错的。 提示 编写非αLS兼容代码是完全可以接受的,只是在编写了这种代码后,就不能保证编译好的L代 码完全支持语言的互操作性。 下面的一个例子是有关区分大小写字母的。I是区分大小写的语言。使用这些语言的开发人员常 常利用区分大小写所提供的灵活性来选择变量名。但 Visual basic2008是不区分大小写的语言。CLS 就要指定CLS兼容代码不使用任何只根据大小写来区分的名称。因此, Visual basic2008代码可以与 CLS兼容代码一起使用。 这个例子说明了CLS的两种工作方式。首先是各个编译器的功能不必强大到支持NET的所有功 能,这将鼓励人们为其他面向NET的编程语言开发编译器。第二,它提供如下保证:如果限制类只 能使用CLS兼容的特性,就要保证用其他兼容语言编写的代码可以使用这个类。 这种方法的优点是使用CLS兼容特性的限制只适用于公共和受保护的类成员和公共类。在类的 私有实现方式中,可以编写非CLS代码,因为其他程序集(托管代码的单元,参见本章后面的内容) 中的代码个能访问这部分代码 这里不深入讨论CLS规范。在一般情况下,CLS对C#代码的影响不会太大,因为C#中的非CIS 兼容特性非常少。 2.垃圾收集 垃圾收集器用来在NET中进行内存管理,特别是它可以恢复正在运行中的应用程序需要的内存 到目前为止, Windows平台凵经使用了两种技术来释放进程向系统动态请求的内存 ●完全以手工方式使应用程序代码完成这些工作。 ●让对象维护引用计数。 让应用程序代码负责释放内存是低级高性能的语言使用的技术,例如C++。这种技术很有效,且 可以让资源在不需要时就释放(一般情况下),但其最大的缺点是频繁出现错误。请求內存的代码还必 须显式通知系统它什么时候不再需要该内存。但这是很容易被遗漏的,从而导致内存泄漏。 尽管现代的廾发环境提供了帮助检测內存泄漏的工具,但它们很难跟踪错误,因为直到內存凵大 量泄漏从而使 Windows拒绝为进程提供资源时,它们才会发挥作用。到那个时候,由于对内存的需 求很大,会使整个计算机变得相当慢 维护引用计数是COM对象米用的一种技术,其方法是每个COM组件都保留一个计数,记录客 户机目前对它的引用数。当这个计数下降到0时,组件就会删除自己,并释放相应的内存和资源。它 带来的问题是仍需要客户机通知组件它们心经完成了内存的使用。只要有一个客户机没有这么做,对 象就仍驻留在内存中。在某些方面,这是比C++内存泄漏更为严重的问题,因为COM对象可能存在 于它自己的进程中,从来不会被系统删除(在CH内存泄漏问题上,系统至少可以在进程中断时释放 所有的内存) NFT运行库采用的方法是垃圾收集器,这是一个程序,其目的是清理内存,方法是所有动态请 求的内存都分配到堆上(所有的语言都是这样处理的,但在NET中,CLR维护它自己的托管堆,以 供NET应用程序使用),当NET检测到给定进程的托管堆己满,需要清理时,就调用垃圾收集器。垃 圾收集器处理目前代码中的所有变量,检查对存储在托管堆上的对象的引用,确定哪些对象可以从代 码中访问-即哪些对象有引用。没有引用的对象就不能再从代码中访问,因而被删除。Java就使用与 此类似的垃圾收集系统。 之所以在NET中使用垃圾收集器,是因为中间语言已用来处理进程。其规则要求,第,不能 引用己有的对象,除非复制已有的引用。第二,中间语言是类型安全的语言。在这里,其含义是如果 存在对对象的任何引用,该引用中就有足够的信息来确定对象的类型 垃墩收集器机制不能和诸如非托管C艹这样的语言一起使用,因为C++允许指针自由地转换数据 类型 垃圾收集器的个重要方面是它的不确定性。换言之,不能保证什么时候会调用垃圾收集器:NET 运行库决定需要它时,就可以调用它(除非明确调用垃圾收集器)。但可以重写这个过程,在代码中调 用垃圾收集器。 3.安全性 NET很好地衤足了 Windows提供的安全机制,因为它提供的安全机制是基于代码的安全性,而 Windows仅提供了基于角色的安全性。 基于角色的安全性建立在运行进程的账户的身份基础上,换而言之,就是准拥有和运行进程。另 方面,基于代码的安全性建立在代码实际执行的任务和代码的可信程度上。由于中间话言提供了强 大的类型安全性,所以CLR可以在运行代码前检查它,以确定是否有需要的安全杖限。NET还提供 了一种机制,可以在运行代码前指定代码需要什么安全权限。 基于代码的安全性非常重要,原因是它降低了运行米历不明的代码的风险(例如代码是从 Internet 上下载来的)。即使代码运行在管珄员账户下,也有叮能使用基于代码的安全性,来确定这段代码是 否仍不能执行管理员账户一般允许执行的某些类型的操作,例如读写环境变量、读写注册表或访 问NET反射特性。 安仝问题详见本书后面的第20章。 4.应用程序域 应用程序域是NET中的一个重要技术改进,它用于减少运行应用程序的系统廾销,这些应用程 序需要与其他稈序分离开来,但仍需要彼此通信。典型的例子是web服务器应用程序,它需要同时 响应许多浏览器请求。因此,要有许多组件实例同时响应这些同时运行的请求。 在NET开发出来以前,可以让这些实例共享同一个进程,但此时一个运行的实例就有可能导致 整个网站的崩溃;也可以把这些实例孤立在不同的进程中,但这样做会增加相关性能的系统开销 到现在为止,孤立代码的唯一方式是通过进程来实现的。在运行一个新的应用程序时,它会在 个进稈环境内运行。 Windows通过地址空间把进程分隔开来。这样,每个进程有4GB的虚拟内存来 存储其数据和可执行代码(4GB对应于32位系统,64位系统要用更多的内存)。 Windows利用额外的 间接方式把这些虚拟内存映射到物理内存或磁盘空间的一个特殊区域中,每个进程都会有不同的映 射,虚拟地址空间块映射的物理内存之间不能有重叠,这种情况如图1-2所示 物型内 逆摆1 扮史内行虫 4GB森积 展盘空 内存 物内存忠 迸程2 4GB根 内存 图1-2 在一般情況下,任何进程都只能通过指定虚拟内存中的一个地址来访问内存-即进程不能直接访 问物理内存,因此个进程不可能访问分配给另个进程的内存。这样就可以确保任何执行出错的代 码不会损害其地址空间以外的数据(注意在 Windows9598上,这些保护措施不像在 Windows NT/2000XP/2003 Vista上那样强大,所以理论上存在应用程序因写入不对应的内存而导致 Windows 崩溃的可能性)。 进程不仅是运行代码的实例相互隔离的一种方式,在 Windows nt/2000XP2003 Vista系统上, 它们还可以构成分配了安全权限和许可的单元。每个进程都有自己的安全标识,明确地表示 Windows 允许该进程可以执行的操作。 进程对确保安全有很大的帮助,而它们的一大缺点是性能。诈多进程常常在一起工作,因此需要 相互通信。一个常见的例子是进程调用一个COM组件,而该COM组件是可执行的,因此需要在它 自己的进稈上运行。在COM中使用代理时也会发生类似的情况。因为进程不能共享任何内存,所以 必须使用一个复杂的编组过程在进程之间复制数据。这对性能有非常大的影响。如果需要使组件一起 工作,但不希望性能有损失,唯一的方法是使用基于DLL的组件,让所有的组件在同一个地址空间 中运行-其风险是执行出错的组件会影响其他组件。 应用程序域是分离组件的一种方式,它不会导致因在进程之闩传送数据而产生的性能问题。其方 法是把任何一个进程分解到多个应用程序域中,每个应用程序域人致对应一个应用程序,执行的每个 线程都运行在一个具体的应用程序域中,如图1-3所示 如果不同的可执行文件都运行在同一个进程空间中,显然它们就能轻松地共享数据,因为理论上 它们可以直接访问彼此的数据。虽然在理论上这是可以实现的,但是CIR会检查每个正在运行的应 用程序的代码,以确保这些代码不偏离它自υ的数据区淢,保证不发生直接访冋其他进程的薮据的情 况。这初看起来是不可能的,如何告诉程序要做什么工作,而又不真正运行它? 进祺:4GE粮内存 应用框序國: 个应用程序使用一些 拟内存 应用程序: 另一个应用框序使用一些成 糗内存 图13 实际上,这么做通常是可能的,因为中间语言拥有强大的类型安全功能。在大多数情况下,除非 代码明确使用不安全的特性,例如指针,否则它使用的数据类型可以确保内存不公被错误地访问。例 如,NE数组类型执行边界检査,以禁止执行超出边界的数组操作。如果运行的应用程序的确需要 与运行在不同应用程序域中的其他应用程序通信或共享数据,就必调用.NET的远程服务 被验证不能访问超出其应用程序域的数据(而不是通过明确的远程机制)的代码就是内存类型安全 的代码,这种代码与运行在同·个进程中但应用程序域不同的类型安全代码·起运行是安全的。 134通过异常处理错误 NE' Framework可以根据异常使用相同的机制处理错误情况,这与Java和C++是一样的。C++ 开发人员应注意到,由于IL有非常强大的类型系统,所以在Ⅱ中以C++的方式使用异常不会带来相 关的性能问题。另外,NET和C#也支持 finally块,这是许多C++开发人员长久以来的愿望。 第14章会详细讨论异常。简要地说,代码的某些领域被看作是异常处理程序例程,每个例程都 能处理某种特殊的错误情况(例如,找不到文件,或拒绝执行某些操作的许可)。这些条件可以定义得 很宽或很窄。异常结构确保在发生错误情况时,执行进程立即跳到最合适的异常处理程序例程上,处 理错误情况。 异常处理的结构还提供了一种方便的方式,当对象包含错误情况的准确信息时,该对象就可以传 送给错误处理例程。这个对象包括给用户提供的相应信息和在代码的什么地方检测到错误的桷切信 息 大多数异常处理结构,包括异常发生时的程序流控制,都是由高级语言处瑆的,例如C#、 Visual Basc2008和C++,任何中间语言中的命令都不支持它。例如,C#使用ty{}、 catch}和 finally{}代 码块来处理它,详见第14章。 NET提供了种基础结构,让面向NET的编译器支持异常处理。特别是它提供了组.NET类 来表示异常,语言的互操作性则允许异常处理代码处理被抛出的异常对象,无论异常处理代码使用什 么语言编写,都是这样。语言的无关性没有体现在C++和Java的异常处理中,但在COM的错误处理 机制中有一定限度的体现。COM的错误处理杋制包括从方法中返回错误代码以及传递错误对象。在 不同的语言中,异常的处理是一致的,这是多语言开发的重要一环。 13.5特性的使用 特性( attribute)是使用C艹+编写COM组件的开发人员很熟悉的一个功能(在 Microsoft的COM接 口定义语言( nterface Definition Language,IDL)中使用特性)。特性最初是为了在程序中提供与某些项 相关的额外信息,以供编详器使用。 NET支持特性,因此现在C++、C#和ⅵ isual basic2008也支持特性。但在NET中,对特性的革 新是健立了·个机制,通过该机制可以在源代码中定义自己的特性。这些用户定义的特性将和对应数 据类型或方法的元数据放在一起,这对于文档说明书十分有用,它们和反射技术一起使用,以根据特 性执行编程任务。另外,与NET的语言无关性的基本原理一样,特性也可以在一种语言的源代码中 定义,而被用另一种语言编写的代码读取。 本书的第13章详细介绍了特性。 14程序集 程序集( assembly)是包含编泽好的、面向 NET Framework的代码的逻辑单元。本章不详细论述程 序集,而在第17章中论述,下面概述其中的要点。 程序集是完全自我描述性的,也是一个逻辑单元而不是物理单元,它可以存储在多个文件中(动 态程序集的确存储在内存中,而不是存储在文件中)。如果一个程序集存储在多个文件中,其中就会 有一个包含入口点的主文件,该文件措述了程序集中的其他文件 注意可执行代码和库代码使用相同的程序集结构。唯一的区别是可执行的程序集包含一个主程序

...展开详情
试读 127P C# 高级编程
立即下载 身份认证VIP会员低至7折
一个资源只可评论一次,评论内容不能少于5个字
您会向同学/朋友/同事推荐我们的CSDN下载吗?
谢谢参与!您的真实评价是我们改进的动力~
关注 私信
上传资源赚钱or赚积分
最新推荐
C# 高级编程 9积分/C币 立即下载
1/127
C# 高级编程第1页
C# 高级编程第2页
C# 高级编程第3页
C# 高级编程第4页
C# 高级编程第5页
C# 高级编程第6页
C# 高级编程第7页
C# 高级编程第8页
C# 高级编程第9页
C# 高级编程第10页
C# 高级编程第11页
C# 高级编程第12页
C# 高级编程第13页
C# 高级编程第14页
C# 高级编程第15页
C# 高级编程第16页
C# 高级编程第17页
C# 高级编程第18页
C# 高级编程第19页
C# 高级编程第20页

试读结束, 可继续阅读

9积分/C币 立即下载