热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

c#中using-添加引用-程序集(详解)以及与c++中include等区别

一、c#中Using无非就三个作用,引入名字空间,减少代码输入量;给名字空间或类型定义一个别名;try-catch的一种替代。二、c#中添加引用的作用是把其它程序集包含到本项目中,就好像在本项目中写的

一、c#中Using无非就三个作用,引入名字空间,减少代码输入量;给名字空间或类型定义一个别名;try-catch的一种替代。

二、c#中添加引用的作用是把其它程序集包含到本项目中,就好像在本项目中写的类一样,因为只有在一个项目中写的类才能互相识别。c#中一个项目中写的两个类是无条件相互识别的,比如在项目中写了Class1和Class2,当然这两个类的名字空间一样。在Class2的方法中可以直接定义Class1的实例(甚至输入代码过程中有智能提示)。我理解,在书写代码的过程中,每定义一个名称,这个名称(不管是类名,方法名还是属性名)一直在随着分号的结束自动添加到自己所在的程序集中的。

三、要区分using和添加引用功能并内有任何必然联系。添加引用有点相当于c++中的include,是把别的程序集中定义的类的信息让本项目识别(因此添加完引用后就有可能出现只能提示)。using表示使用了某个名字空间,完全可以从来不用using来引入名字空间,使用某个程序集中的类型时使用包含名字空间的全名,只不过这样书写起代码太麻烦。所以using引入名字空间完全是为了书写代码方便,而添加引用是为了将别人写的类导入到自己的项目中来(就好像增加了一个新写的类一样)使用。

四、c++中也有using名字空间语句,它的名字空间和c#中的名字空间完全一样,只是为了避免重名而已。C++中的include语句只起到将某些代码原样复制到所在位置。我理解由于c++不想c#中那样有程序集的概念,不会在书写代码的过程中自动把定义的类型添加到程序集中,所以书写的各个类(不同的.cpp源文件)互相不识别,需要通过include来提前声明一个表示这个类型已经定义过了(和函数声明一样),可以在其它源文件中找到。

五、我总结,C#中没有“使用前先声明”这样的说法,只有“使用前必须在程序集中能找到”这样的说法,只要存在程序集中就有智能提示。而C++中必须遵循“使用前先声明”这样的说法,只要声明过来就有智能提示。之所以这样,可能是因为C#的源代码纯是由一个个类组成的,便于组织成程序集单元。而C++中的源代码灵活性太高,不易组成固定格式的程序集或者因为历史原因没用程序集这样的概念,所以有了两者对于“先声明后使用”的区别对待。

六、补充下C#中程序集的概念:

程序集(Assembly)是组织程序的逻辑单元,我们编写好的代码最终都会被编译器编译为若干个程序集。需要指出的是程序集只是逻辑上的划分,一个程序集可以只由一个文件组成,也可以由多个文件组成。单文件程序集的所有内容都存放在一个文件中,是最简单也是最常用的类型;多文件程序集则把它的内容分别放在多个文件中。最常见的两种程序集在物理上体现为exe文件和dll文件。

程序集由程序集元数据、类型元数据、MSIL代码和资源四部分组成(这几个部分可能在不同的物理文件中),如下图

 

1、其中,程序集元数据也叫“清单”【估计为了版本控制等作用】,它记录了程序集的许多重要信息,是程序集进行自我说明的核心文档。当程序运行时,CLR仅通过这份清单就能获取运行程序集所必需的全部信息。清单主要包括如下信息:

(1)标识信息(包括程序集的名称、版本、文化和公钥等)

(2)文件列表(程序集由哪些文件组成)

(3)引用程序集列表(该程序集所引用的其它程序集

(4)一组许可要求(运行这个程序集需要的许可)

注意:我把“引用的程序集列表加粗显示”是因为,这点很重要,因为真是因为有这个因素,比如我们在主程序集main.exe中引用了A程序集a.dll,而a.dll又引入了b.dll。那么我们在添加A程序集的引用a.dll后还需不需要添加b.dll呢?原来我一直以为需要,实际上是对程序集理解错误了,不要把程序集单纯的理解就和一个cs代码文件一样,他其实是一个比cs内容更丰富的东西。实际上运行时,main.exe先加载入内存,同时分析main.exe还包括引用了哪些其他程序集,发现引用了a.dll,所以main.exe加载入内存后又紧接着加载a.dll进入内存,又分析a.dll发现引用了b.dll,紧接着又加载b.dll进入内存,但经过测试发现如果没有发现a.dll或b.dll则在程序刚开始运行时不一定出错,只有当使用到对应dll中的东西时才提示“未能加载程序集或程序集版本号不匹配之类的错误”。(有点静态链接的意思,在运行初始阶段就把所有需要的库都加载进入内存了,只不过c++的静态链接库全部被写入到了exe中,c#中没有把dll写入exe中而已。当然要实现类似动态链接那样用到那个库时才加载对应的dll则在C#中可以使用反射机制。)

另外,程序引用中的第三方控件的版本号(我这边是路径导致的)和最终生成的程序集清单所需的版本号并不相符的问题?

   .net的CLR在执行一个程序时(如.exe)时或使用一个.dll时,他会首先查看其程序集(.exe或.dll)的程序集清单,找到运行该程序所引用的程序集并加载。.net会按一定的路径搜索,加载.若加载的版本和程序清单中的不一致时就会出现类似"程序集清单定义与程序集引用不匹配"报错。【这说明程序集列表还含有版本信息,不光只有名称】

【另外,对于上面的情况,如果b.dll位于全局程序集缓存GAC中则这个b.dll并不写入到引用程序集列表中,所以不能简单的把这些dll复制到exe的输出目录中然后拷贝到其他机器上运行,因为运行时即使b.dll存在bin目录中,但仍然不载入内存,如果其他机子的GAC中没有b.dll的话就会提示缺少b.dll的错误,我在引入oracle.dataaccess.dll的时候就出现这个情况】

关于添加引用的方法和问题详见:http://msdn.microsoft.com/zh-cn/library/windows/hardware/ez524kew(v=vs.90)

 

2、类型元数据列举了程序集中包含的类型信息【比如帮助实现了书写代码时的智能提示等作用】,详细说明了程序集中定义了哪些类,每个类包含了哪些属性和函数,每个函数有哪些参数和返回值类型,等等。

 

3、MSIL是程序集中真正在运行时使用的东西,也是核心(也就是我们写的真正的代码)。也就是我们写的代码真正在运行中的体现。相比之下“列表”和类型元数据只不过是.NET帮我们自动生成的辅助信息,只不过为了运行前的一些工作便利罢了。

 

4、资源包括图像、图标、声音等资源。

 

总之,程序集是自我说明的【通过元数据这种辅助信息】,这些自我说明文档提供了运行程序集所必须的信息,这样我们就不必依靠注册表等外部信息就能运行程序。所有的信息存于一处,这种设计方式也大大简化了程序的安装过程。

需要澄清的是,命名空间与程序集并不总是一一对应的。命名空间是类名的扩展,一个程序集可以包含多个命名空间,一个命名空间也可以分布在多个程序集中。


推荐阅读
author-avatar
柏拉图恋情
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有