100162732.htm
来自「C#高级编程(第三版),顶死你们。。 。up」· HTM 代码 · 共 298 行 · 第 1/5 页
HTM
298 行
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">前面介绍了使用</span><span lang="EN-US">.NET</span><span style="FONT-FAMILY: 宋体">意味着要编译为中间语言,即需要使用传统的面向对象的方法来编程。但这并不能提供语言的互操作性。毕竟,</span><span lang="EN-US">C++</span><span style="FONT-FAMILY: 宋体">和</span><span lang="EN-US">Java</span><span style="FONT-FAMILY: 宋体">都使用相同的面向对象的范型,但它们仍不是可交互操作的语言。下面需要详细探讨一下语言互操作性的概念。</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">首先,需要确定一下语言互操作性的含义。毕竟,</span><span lang="EN-US">COM</span><span style="FONT-FAMILY: 宋体">允许以不同语言编写的组件一起工作,即可以调用彼此的方法。这就足够了吗?</span><span lang="EN-US">COM</span><span style="FONT-FAMILY: 宋体">是一个二进制标准,允许组件实例化其他组件,调用它们的方法或属性,而无需考虑编写相关组件的语言。但为了实现这个功能,每个对象都必须通过</span><span lang="EN-US">COM</span><span style="FONT-FAMILY: 宋体">运行库来实例化,通过接口来访问。根据关系组件的线程模型,不同线程上内存空间和运行组件之间要编组数据,这还可能造成很大的性能损失。在极端情况下,组件驻留在可执行文件中,而不是</span><span lang="EN-US">DLL</span><span style="FONT-FAMILY: 宋体">文件中,还必须创建单独的过程来运行它们。重要的是组件要能与其他组件通信,但仅通过</span><span lang="EN-US">COM</span><span style="FONT-FAMILY: 宋体">运行库进行通信。无论</span><span lang="EN-US">COM</span><span style="FONT-FAMILY: 宋体">是用于允许使用不同语言的组件直接彼此通信,或者创建彼此的实例,系统都把</span><span lang="EN-US">COM</span><span style="FONT-FAMILY: 宋体">作为中间件来处理。不仅如此,</span><span lang="EN-US">COM</span><span style="FONT-FAMILY: 宋体">结构还不允许利用继承实现,即它丧失了面向对象编程的许多优势。</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">一个相关的问题是,在调试时,仍必须单独调试用不同语言编写的组件。这样就不可能在调试器上调试不同语言的代码了。语言互操作性的真正含义是用一种语言编写的类应能直接与用另一种语言编写的类通信。特别是:</span></p>
<p class="1" style="MARGIN-LEFT: 37.55pt; TEXT-INDENT: -16.1pt"><span lang="EN-US">●<span style="FONT: 7pt 'Times New Roman'"> </span></span><span style="FONT-FAMILY: 宋体">用一种语言编写的类应能继承用另一种语言编写的类。</span></p>
<p class="1" style="MARGIN-LEFT: 37.55pt; TEXT-INDENT: -16.1pt"><span lang="EN-US">●<span style="FONT: 7pt 'Times New Roman'"> </span></span><span style="FONT-FAMILY: 宋体">一个类应能包含另一个类的实例,而不管它们是使用什么语言编写的。</span></p>
<p class="1" style="MARGIN-LEFT: 37.55pt; TEXT-INDENT: -16.1pt"><span lang="EN-US">●<span style="FONT: 7pt 'Times New Roman'"> </span></span><span style="FONT-FAMILY: 宋体">一个对象应能直接调用用其他语言编写的另一个对象的方法。</span></p>
<p class="1" style="MARGIN-LEFT: 37.55pt; TEXT-INDENT: -16.1pt"><span lang="EN-US">●<span style="FONT: 7pt 'Times New Roman'"> </span></span><span style="FONT-FAMILY: 宋体">对象</span><span lang="EN-US">(</span><span style="FONT-FAMILY: 宋体">或对象的引用</span><span lang="EN-US">)</span><span style="FONT-FAMILY: 宋体">应能在方法之间传递。</span></p>
<p class="1" style="MARGIN-LEFT: 37.55pt; TEXT-INDENT: -16.1pt"><span lang="EN-US">●<span style="FONT: 7pt 'Times New Roman'"> </span></span><span style="FONT-FAMILY: 宋体">在不同的语言之间调用方法时,应能在调试器中调试这些方法调用,即调试不同语言编写的源代码。</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">这是一个雄心勃勃的目标,但令人惊讶的是,</span><span lang="EN-US">.NET</span><span style="FONT-FAMILY: 宋体">和中间语言已经实现了这个目标。在调试器上调试方法时,</span><span lang="EN-US">Visual Studio .NET IDE</span><span style="FONT-FAMILY: 宋体">提供了这样的工具</span><span lang="EN-US">(</span><span style="FONT-FAMILY: 宋体">不是</span><span lang="EN-US">CLR</span><span style="FONT-FAMILY: 宋体">提供的</span><span lang="EN-US">)</span><span style="FONT-FAMILY: 宋体">。</span></p>
<h3 style="MARGIN: 8.15pt 0cm"><span lang="EN-US">1.3.2</span><span lang="EN-US"> </span><span style="FONT-FAMILY: 黑体">值类型和引用类型</span></h3>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">与其他编程语言一样,中间语言提供了许多预定义的基本数据类型。它的一个特性是值类型和引用类型有明显的区别。对于值类型,变量直接保存其数据,而对于引用类型,变量仅保存地址,对应的数据可以在该地址中找到。</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">在</span><span lang="EN-US">C++</span><span style="FONT-FAMILY: 宋体">中,引用类型类似于通过指针来访问变量,而在</span><span lang="EN-US">Visual Basic</span><span style="FONT-FAMILY: 宋体">中,与引用类型最相似的是对象,</span><span lang="EN-US" style="LETTER-SPACING: -0.5pt">VB6</span><span style="FONT-FAMILY: 宋体; LETTER-SPACING: -0.5pt">总</span><span style="FONT-FAMILY: 宋体">是通过引用来访问对象。中间语言也有数据存储的规范:引用类型的实例总是存储在一个名为托管堆的内存区域中,值类型一般存储在堆栈中</span><span lang="EN-US">(</span><span style="FONT-FAMILY: 宋体">但如果值类型在引用类型中声明为字段,它们就内联存储在堆中</span><span lang="EN-US">)</span><span style="FONT-FAMILY: 宋体">。第</span><span lang="EN-US">3</span><span style="FONT-FAMILY: 宋体">章讨论堆栈和堆,及其工作原理。</span></p>
<h3 style="MARGIN: 8.15pt 0cm"><span lang="EN-US">1.3.3</span><span lang="EN-US"> </span><span style="FONT-FAMILY: 黑体">强</span><span style="FONT-FAMILY: 黑体">数据类型</span></h3>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">中间语言的一个重要方面是它基于强数据类型。所有的变量都清晰地标记为属于某个特定数据类型</span><span lang="EN-US">(</span><span style="FONT-FAMILY: 宋体">在中间语言中没有</span><span lang="EN-US">Visual Basic</span><span style="FONT-FAMILY: 宋体">和脚本语言识别的</span><span lang="EN-US">Variant</span><span style="FONT-FAMILY: 宋体">数据类型</span><span lang="EN-US">)</span><span style="FONT-FAMILY: 宋体">。特别是中间语言一般不允许对模糊的数据类型执行任何操作。</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">开发人员习惯于传递变量,而无需担心它们的类型。因为</span><span lang="EN-US">VB6</span><span style="FONT-FAMILY: 宋体">会自动进行所需的类型转换。</span><span lang="EN-US">C++</span><span style="FONT-FAMILY: 宋体">开发人员习惯于在不同类型之间转换指针类型。执行这类操作将大大提高性能,但破坏了类型的安全性。因此,这类操作只能在非常特殊的情况下进行,在某些编译为托管代码的语言中也仅支持非常特殊的情况。确实,指针</span><span lang="EN-US">(</span><span style="FONT-FAMILY: 宋体">相对于引用</span><span lang="EN-US">)</span><span style="FONT-FAMILY: 宋体">只能在标记了的</span><span lang="EN-US">C#</span><span style="FONT-FAMILY: 宋体">代码块中使用,但在</span><span lang="EN-US">VB</span><span style="FONT-FAMILY: 宋体">中不能使用</span><span lang="EN-US">(</span><span style="FONT-FAMILY: 宋体">但一般在托管</span><span lang="EN-US">C++</span><span style="FONT-FAMILY: 宋体">中允许使用</span><span lang="EN-US">)</span><span style="FONT-FAMILY: 宋体">。在代码中使用指针会立即导致</span><span lang="EN-US">CLR</span><span style="FONT-FAMILY: 宋体">提供的内存类型安全性检查失败。</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">注意,一些与</span><span lang="EN-US">.NET</span><span style="FONT-FAMILY: 宋体">兼容的语言。例如</span><span lang="EN-US">VB.NET</span><span style="FONT-FAMILY: 宋体">,在类型化方面上要求仍比较松,但这是可以的,因为编译器在后台确保在生成的</span><span lang="EN-US">IL</span><span style="FONT-FAMILY: 宋体">上强制类型安全。</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">尽管强迫实现类型的安全性最初会降低性能,但在许多情况下,我们从</span><span lang="EN-US">.NET</span><span style="FONT-FAMILY: 宋体">提供的、依赖于类型安全的服务中获得的好处更多。这些服务包括:</span></p>
<p class="1" style="MARGIN-LEFT: 37.55pt; TEXT-INDENT: -16.1pt"><span lang="EN-US">●<span style="FONT: 7pt 'Times New Roman'"> </span></span><span style="FONT-FAMILY: 宋体">语言的互操作性</span></p>
<p class="1" style="MARGIN-LEFT: 37.55pt; TEXT-INDENT: -16.1pt"><span lang="EN-US">●<span style="FONT: 7pt 'Times New Roman'"> </span></span><span style="FONT-FAMILY: 宋体">垃圾收集</span></p>
<p class="1" style="MARGIN-LEFT: 37.55pt; TEXT-INDENT: -16.1pt"><span lang="EN-US">●<span style="FONT: 7pt 'Times New Roman'"> </span></span><span style="FONT-FAMILY: 宋体">安全性</span></p>
<p class="1" style="MARGIN-LEFT: 37.55pt; TEXT-INDENT: -16.1pt"><span lang="EN-US">●<span style="FONT: 7pt 'Times New Roman'"> </span></span><span style="FONT-FAMILY: 宋体">应用程序域</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">下面学习讨论强数据类型化对于这些</span><span lang="EN-US">.NET</span><span style="FONT-FAMILY: 宋体">特性非常重要的原因。</span></p>
<h4 style="TEXT-INDENT: 21.45pt"><span lang="EN-US">1. </span><span style="FONT-FAMILY: 黑体">语言互操作性中强数据类型的重要性</span></h4>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">如果类派生其他类,或包含其他类的实例,它就需要知道其他类使用的所有数据类型,这就是强数据类型非常重要的原因。实际上,过去没有任何认同的系统指定这些信息,从而成为语言继承和交互操作的真正障碍。这类信息不只是在一个标准的可执行文件或</span><span lang="EN-US">DLL</span><span style="FONT-FAMILY: 宋体">中出现。</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">假定</span><span lang="EN-US">VB.NET</span><span style="FONT-FAMILY: 宋体">类中的一个方法被定义为返回一个整型<span style="LETTER-SPACING: -0.5pt">——</span></span><span lang="EN-US">VB.NET</span><span style="FONT-FAMILY: 宋体">可以使用的标准数据类型之一。但</span><span lang="EN-US">C#</span><span style="FONT-FAMILY: 宋体">没有该名称的数据类型。显然,我们只能从该类中派生,再使用这个方法,如果编译器知道如何把</span><span lang="EN-US">VB.NET</span><span style="FONT-FAMILY: 宋体">的整型类型映射为</span><span lang="EN-US">C#</span><span style="FONT-FAMILY: 宋体">定义的某种已知类型,就可以在</span><span lang="EN-US">C#</span><span style="FONT-FAMILY: 宋体">代码中使用返回的类型。这个问题在</span><span lang="EN-US">.NET</span><span style="FONT-FAMILY: 宋体">中是如何解决的?</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">通用类型系统</span><span lang="EN-US"> (CTS)</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">中使用通用类型系统</span><span lang="EN-US"> (CTS)</span><span style="FONT-FAMILY: 宋体">得到了解决。</span><span lang="EN-US">CTS</span><span style="FONT-FAMILY: 宋体">定义了可以在中间语言中使用的预定义数据类型,所有用于</span><span lang="EN-US">.NET Framework</span><span style="FONT-FAMILY: 宋体">的语言都可以生成最终基于这些类型的编译代码。</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">例如,</span><span lang="EN-US">VB.NET</span><span style="FONT-FAMILY: 宋体">的整型实际上是一个</span><span lang="EN-US">32</span><span style="FONT-FAMILY: 宋体">位有符号的整数,它实际映射为中间语言类型</span><span lang="EN-US">Int32</span><span style="FONT-FAMILY: 宋体">。因此在中间语言代码中就指定这种数据类型。</span><span lang="EN-US">C#</span><span style="FONT-FAMILY: 宋体">编译器可以使用这种类型,所以就不会有问题了。在源代码中,</span><span lang="EN-US">C#</span><span style="FONT-FAMILY: 宋体">用关键字</span><span lang="EN-US">int</span><span style="FONT-FAMILY: 宋体">来表示</span><span lang="EN-US">Int32</span><span style="FONT-FAMILY: 宋体">,所以编译器就认为</span><span lang="EN-US">VB.NET</span><span style="FONT-FAMILY: 宋体">方法返回一个</span><span lang="EN-US">int</span><span style="FONT-FAMILY: 宋体">类型的值。</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">通用类型系统不仅指定了基本数据类型,还定义了一个内容丰富的类型层次结构,其中包含设计合理的位置,在这些位置上,代码允许定义它自己的类型。通用类型系统的层次结构反映了中间语言的单一继承的面向对象的方法,如图</span><span lang="EN-US">1-1</span><span style="FONT-FAMILY: 宋体">所示。</span></p>
<p align="center"><span lang="EN-US"><img height="300" alt="" width="480" src="01/image001.gif" /></span></p>
<p style="MARGIN-BOTTOM: 8.15pt" align="center"><span style="FONT-FAMILY: 宋体">图</span><span lang="EN-US"> 1-1</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">这个树形结构中的类型说明如表</span><span lang="EN-US">1-1</span><span style="FONT-FAMILY: 宋体">所示。</span></p>
<p style="MARGIN-TOP: 8.15pt" align="center"><span style="FONT-FAMILY: 黑体">表</span><span lang="EN-US"> 1-1</span></p>
<div align="center">
<table class="MsoNormalTable" style="BORDER-RIGHT: medium none; BORDER-TOP: medium none; MARGIN-LEFT: -6.3pt; BORDER-LEFT: medium none; BORDER-BOTTOM: medium none; BORDER-COLLAPSE: collapse" cellspacing="0" cellpadding="0" border="1">
<tbody>
<tr>
<td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 9.9pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 9.9pt; PADDING-BOTTOM: 1.4pt; BORDER-LEFT: medium none; WIDTH: 141.3pt; PADDING-TOP: 1.4pt; BORDER-BOTTOM: windowtext 1pt solid" valign="top" width="188">
<p class="a2"><span style="FONT-FAMILY: 黑体">类</span><span lang="EN-US" style="FONT-FAMILY: 'Times New Roman'"> </span><span style="FONT-FAMILY: 黑体">型</span></p>
</td>
<td style="BORDER-RIGHT: medium none; PADDING-RIGHT: 9.9pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 9.9pt; PADDING-BOTTOM: 1.4pt; BORDER-LEFT: medium none; WIDTH: 296.5pt; PADDING-TOP: 1.4pt; BORDER-BOTTOM: windowtext 1pt solid" valign="top" width="395">
<p class="a2"><span style="FONT-FAMILY: 黑体">含</span><span lang="EN-US" style="FONT-FAMILY: 'Times New Roman'"> </span><span style="FONT-FAMILY: 黑体">义</span></p>
</td>
</tr>
<tr>
<td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 9.9pt; BORDER-TOP: medium none; PADDING-LEFT: 9.9pt; PADDING-BOTTOM: 1.4pt; BORDER-LEFT: medium none; WIDTH: 141.3pt; PADDING-TOP: 1.4pt; BORDER-BOTTOM: windowtext 1pt solid" valign="top" width="188">
<p class="a4" style="MARGIN-LEFT: 10.7pt"><span lang="EN-US">Type</span></p>
</td>
<td style="BORDER-RIGHT: medium none; PADDING-RIGHT: 9.9pt; BORDER-TOP: medium none; PADDING-LEFT: 9.9pt; PADDING-BOTTOM: 1.4pt; BORDER-LEFT: medium none; WIDTH: 296.5pt; PADDING-TOP: 1.4pt; BORDER-BOTTOM: windowtext 1pt solid" valign="top" width="395">
<p class="a4" style="MARGIN-LEFT: 0cm"><span style="FONT-FAMILY: 宋体">代表任何类型的基类</span></p>
</td>
</tr>
<tr>
<td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 9.9pt; BORDER-TOP: medium none; PADDING-LEFT: 9.9pt; PADDING-BOTTOM: 1.4pt; BORDER-LEFT: medium none; WIDTH: 141.3pt; PADDING-TOP: 1.4pt; BORDER-BOTTOM: windowtext 1pt solid" valign="top" width="188">
<p class="a4" style="MARGIN-LEFT: 10.7pt"><span lang="EN-US">Value Type</span></p>
</td>
<td style="BORDER-RIGHT: medium none; PADDING-RIGHT: 9.9pt; BORDER-TOP: medium none; PADDING-LEFT: 9.9pt; PADDING-BOTTOM: 1.4pt; BORDER-LEFT: medium none; WIDTH: 296.5pt; PADDING-TOP: 1.4pt; BORDER-BOTTOM: windowtext 1pt solid" valign="top" width="395">
<p class="a4" style="MARGIN-LEFT: 0cm"><span style="FONT-FAMILY: 宋体">代表任何值类型的基类</span></p>
</td>
</tr>
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?