文章目录
22.1 引用其他程序集
在许多项目中,会使用其他程序集的类或类型,而不仅仅是自己声明的。这些程序集(称为类库)可能来自 BCL 或第三方供应商,也可以是自己创建的。通常这些程序集文件的名称以 .dll 扩展名结尾,而不是 .exe。
![image-20240112104716131](https://img-blog.csdnimg.cn/img_convert/d717115bdb5c5d294f42953c25081b38.png#pic_center)
![image-20240112104630330](https://img-blog.csdnimg.cn/img_convert/a460c97fd96dddc4b645be8e31ff094a.png#pic_center)
假设还要写一个名为 MyWidgets 的程序,而且想使用 SquareWidget 类。在代码中没有声明类 SquareWidget,使用的是定义在 SuperLib 中的类。在编译程序时,需要给编译器添加该引用。
![image-20240112104937515](https://img-blog.csdnimg.cn/img_convert/aab6447eaa680208d0c04dcc9548a3f3.png#pic_center)
在 Rider 中,右键项目,选择“添加” ->
“引用”,选择下方的“添加自”按钮,找到对应的程序集即可。
![image-20240112105453161](https://img-blog.csdnimg.cn/img_convert/80939ccdb83519105bf2431bb13daab8.png#pic_center)
![image-20240112105603092](https://img-blog.csdnimg.cn/img_convert/123dae131e0e7c19daa4a7477c6317b3.png#pic_center)
添加引用后,即可编译 MyWidgets。
![image-20240112105753187](https://img-blog.csdnimg.cn/img_convert/a76b09098db1eac788d8ac8a437a9f3d.png#pic_center)
mscorlib 库
有一个类库,几乎先前的每个示例中都使用了它,即包含 Console 类的类库。该类库被定义在 mscorlib 程序集中的 mscorlib.dll 文件里。mscorlib 包含 C# 类型及大部分 .NET 语言基本类型的定义,在编译时,它必须被引用,因此不显示放在引用目录中。
因此,算上 mscorlib,图 22.3 的过程看起来更像是图 22.4 描述的那样。
![image-20240112110057102](https://img-blog.csdnimg.cn/img_convert/86eb3bc160cccbcd284779bc1cb8ade1.png#pic_center)
潜在的问题
若想扩展上述类的能力,使用名为 CircleWidget 的类,并将其定义在 UltraLib 的程序集中。MyWidgets 的源代码如下,创建一个 SquareWidget 对象和一个 CircleWidget 对象,分别定义在 SuperLib 和 UltraLib 中。
![image-20240112110502799](https://img-blog.csdnimg.cn/img_convert/f43a38179680a997d5dbb885295b21ee.png#pic_center)
类库 UltraLib 的源代码如下所示,并将 UltraLib 编译成 dll,加入到项目引用列表中。注意,除了 CircleWidget 类外,还声明了一个名为 SquareWidget 的类。
![image-20240112110702481](https://img-blog.csdnimg.cn/img_convert/063c48a86aae79ce847b1625af0b23bb.png#pic_center)
由于两个库都含有名为 SquareWidget 的类,编译时会产生错误信息,因为编译器不知道使用 SquareWidget 类的哪个版本。
![image-20240112111012114](https://img-blog.csdnimg.cn/img_convert/f6a51e98568adf3cab7dbbddbd7033a3.png#pic_center)
22.2 命名空间
- 命名空间可视为一个字符串,加在类名或类型名前面,通过点分隔。
- 命名空间名、分隔点、类名三者共同组成类的完全限定名。
- 命名空间是共享命名空间名的一组类和类型。
![image-20240112151644643](https://img-blog.csdnimg.cn/img_convert/babd66f50c6e53f0d1f2227b79ea0477.png#pic_center)
使用命名空间将一组类型组织在一起并命名。
![image-20240112151816672](https://img-blog.csdnimg.cn/img_convert/d1d6e4e64ad512bc9e74c313b9e5d18d.png#pic_center)
例如,创建 MyCorp.SuperLib 命名空间并在其中声明 SquareWidget 类。
![image-20240112152123128](https://img-blog.csdnimg.cn/img_convert/5f4a5f165693d645f266a8b2805f4fd0.png#pic_center)
当 MyCorp 公司提供更新的程序集时,可以按照如下方式修改。
![image-20240112152209194](https://img-blog.csdnimg.cn/img_convert/ae0f8ed9d90b25bdc5dc6a07d611459c.png#pic_center)
如果 UltraLib 程序集也被使用,那么编译过程下。
![image-20240112152254624](https://img-blog.csdnimg.cn/img_convert/4baca44d8f168ea4376395f2e6ef32c4.png#pic_center)
22.2.1 命名空间名称
- 命名空间名称可以是任何有效标识符,区分大小写。
- 命名空间名称可以包含任意数量的句点符号,用于将层次化组织类型。
![image-20240112152501201](https://img-blog.csdnimg.cn/img_convert/debaf55b9c61144259b74e1e7f2d378f.png#pic_center)
使用命名空间要点如下:
- 以公司名称开头。
- 在公司名之后跟着技术名称。
- 不要与类或类型名称相同。
22.2.2 命名空间的补充
- 命名空间内,每个类型名必须有别于所有其他类型。
- 命名空间内的类型称为命名空间的成员。
- 源文件可以包含任意树木的命名空间声明,可以顺序也可以嵌套。
![image-20240112152744401](https://img-blog.csdnimg.cn/img_convert/8f163cfbab584e036a89f675940297ad.png#pic_center)
22.2.3 命名空间跨文件伸展
命名空间是非封闭的,可以在源文件后面或其他源文件中使用。
![image-20240112152909337](https://img-blog.csdnimg.cn/img_convert/1d3a13987edeb491dc14b8ae1b1eaa3d.png#pic_center)
![image-20240112153030894](https://img-blog.csdnimg.cn/img_convert/3b9227b50cd12e56a9b4069101f7fe2b.png#pic_center)
22.2.4 嵌套命名空间
-
文本嵌套
将命名空间的声明放在一个命名空间声明体内部。
-
分离的声明
为嵌套命名空间创建单独的声明,但必须在声明中使用完全限定名。
![image-20240112153510335](https://img-blog.csdnimg.cn/img_convert/923ea46330e57ff0e9a20f73362f8a38.png#pic_center)
![image-20240112153558282](https://img-blog.csdnimg.cn/img_convert/cac241a92cb562616a7d0922b4190d12.png#pic_center)
22.3 using 指令
using 指令包含 2 大作用:
- using 命名空间指令。
- using 别名指令。
关于 using 指令的要点如下:
- 必须放在源文件的顶端,在任何类型声明之前。
- 应用于当前源文件中的所有命名空间。
22.3.1 using 命名空间指令
通过在源文件顶端放置 using 命名空间指令以避免使用长名称。
![image-20240112154615000](https://img-blog.csdnimg.cn/img_convert/373fc48e25c9b444bf84e5829d1ecf5a.png#pic_center)
下面的代码使用 using 命名空间指令来描述该代码来自 System 命名空间的类或其他类型。
![image-20240112154634804](https://img-blog.csdnimg.cn/img_convert/297b55c6ebb64ec12d2fab2a14c4723c.png#pic_center)
22.3.2 using 别名指令
![image-20240112154913312](https://img-blog.csdnimg.cn/img_convert/cddbea5ca648bc8b9573d71ef46ad374.png#pic_center)
using 别名指令允许起一个别名给:
- 命名空间。
- 命名空间捏的一个类型。
![image-20240112155352194](https://img-blog.csdnimg.cn/img_convert/2b14e9b330405cbb7d8166b45d1a75bc.png#pic_center)
- 前两行告诉编译器,Syst 是 命名空间 System 的别名,SC 是类 System.Consle 的别名。
- Main 的第一条语句使用命名空间 System 的别名,第二条语句使用完全限定名,第三条语句使用类的别名。
22.3.3 using static 指令
使用 using static 指令引用给定命名空间中的特定类、结构体或枚举,以不带任何前缀地进行访问。
![image-20240112155555697](https://img-blog.csdnimg.cn/img_convert/2dcfbe897c2020bef206adf6dbfa61b0.png#pic_center)
using static 指令指定的类本身可以不是静态的,类中非静态类型成员不会被 using static 指令导入。
22.4 程序集的结构
程序集本身不包含本地机器代码,而是包含公共中间语言代码。此外,还包含即时编译器(JIT),在运行时将 CIL 转换为本机代码所需要的一切信息。程序集的文件扩展名通常为 .exe 或 .dll。
单文件程序集
大部分程序集由一个单独的文件构成:
-
程序集清单。
- 程序集标识符。
- 组成程序集的文件列表。
- 一个指示程序集中内容在哪里的地图。
- 关于引用的其他程序集的信息。
-
类型元数据。
包含程序集中定义的所有类型的信息。
-
CIL 中间代码。
-
资源部分。
该部分可选。可以包含图形或语言资源。
![image-20240112161415922](https://img-blog.csdnimg.cn/img_convert/8f14fcf9c639c09ae81891702e1c58dd.png#pic_center)
多文件程序集
程序集代码文件称为模块。尽管大部分程序集由单个文件构成,但有些程序集含有多个文件。对于有多个模块的程序集,一个文件是主模块,其他为次要模块。
- 主模块含有程序集的清单和次要模块的引用。
- 次要模块的文件名以扩展名 .netmodule 结尾。
- 多文件程序集被视为一个单元,一起部署并一起定版。
![image-20240112161836105](https://img-blog.csdnimg.cn/img_convert/f2855fe444e28a25a9076d3b0c826486.png#pic_center)
22.5 程序集标识符
在 .NET 框架中,程序集的文件名相对不重要,更重要的是程序集的标识符,其包含 4 个组成部分:
-
简单名称。
不带文件扩展名的文件名,也称为程序集名或友好名称。
-
版本号。
形式为 MajorVersion.MinorVersion.Build.Revision,例如:2.0.35.9。
-
文化信息。
一个由 2 ~ 5 个字符组成的字符串,代表一种语言、国家或地区。例如,没过使用的英语文化名是 en-US,德国使用的德语文化是de-DE。
-
公钥。
由程序集公司生产的唯一字符串(128 字节)。
![image-20240112162522780](https://img-blog.csdnimg.cn/img_convert/d019959505fc1dfad1c45852bbd920d1.png#pic_center)
![image-20240112162552644](https://img-blog.csdnimg.cn/img_convert/3661add1181a039e0bd6fbd21c4a85d7.png#pic_center)