本节内容:
1、剖析Hello,World程序
1.1初始类(class)与名称空间(namespace)
2、类库的引用
2.1DLL的引用(黑盒引用)
2.2项目引用(白盒引用)
2.3建立自己的类库项目
3、依赖关系
4、排除错误
1、剖析Hello,World程序
1.1、类(class)构成程序的主体
1.2、名称空间(namespace)以树型结构组织类(和其他类型)
例如Button和Path类
命名空间可以有效的避免同名的类有冲突。
C#是完全面向对象的语言,整个程序都包含在一个类里面:class Program{}
当有引入命名空间:Using....相当于告诉程序如果我要写一个类的时候,如果我没有把这个类的命名空间在类名前标出来,就去我引用的命名空间里面检索一遍,看哪个命名空间里面有这个类,就用这个命名空间里面的类就可以了。
比如:Console类有两种引用方式:
第一种:不引入命名空间:System.Console.WriteLine();
如果还要用System里面的类每一次都要向上面一样在类前加前缀(这叫权限命名),显得冗余。
那可不可以我写Console编译器就知道它是从System里来的呢?
第二种:引入命名空间:
Using System;
Console.WriteLine();以后引用System命名空间里面的类就不用加前缀了,这就是引用命名空间的方便之处。
*小技巧:找到某个类的命名空间。两种方法
第一种:是通过文档来知道,打开导入的本地帮助文档,搜索该类。
第二种:相对简单的方法:把鼠标放在这个类上面左下角会出现一个蓝色智能标记,有两个选项:Using System和System.Console分别表示引用命名空间的两种方法。(编译器比较聪明猜到了这个类属于哪个命名空间)
注意不能图方便把全部的命名空间都引用进来,会发生冲突。因为命名空间以树型结构来组织类的,
不同的树型结构也有可能有相同的类存在,这时若使用引入命名空间的方法来引用相关类就容易造成混乱;比如
Path类既属于System.IO命名空间也属于System命名空间,则这时就不知道引用哪个命名空间里面的Path类了。
这时应该采用第一种不引入命名空间的方法才能准确的引用不同命名空间相同名字的类。
如:System.Path或者System.IO.Path就可以清楚地区分不同命名空间里面名字相同的类了。
*再比如Button类有十多种,这时就凸显出了命名空间的重要性,如果没有命名空间就只能有一个Button类了,有效的解决类名的冲突。
*这样也给我们一个设计思路,当我们在设计类的时候要给类一个精确地名字同时要非常精确的把它放在它应该在的命名空间里面,这样既方便自己写程序,也方便别人用我们程序的时候也能快速和舒服的找到我们的类。比如:自己创建了一个.h文件,在别处引用时不仅要引入头文件.h还要引入这个自定义类的命名空间,让他独一无二。
2、类库的使用
就好比书,虽然知道这本书是哪个图书馆的,如果连图书馆都没有用可能把书拿出来吗?
所以有:类和命名空间是放在叫做类库的地方,类库就是类和名称空间的物理基础
(不同的技术类型的项目会默认引用不同的类库)
2.1、DLL(类库)(Dynamic link library)动态链接库,的引用(黑盒引用,无源代码)*NuGet简介.
如果要使用相应的命名空间和类就要先引用相应的类库。在那里找类库呢?解决方案->引用,里面的都是你新建里不同类型程序程序默认引用的类库,双击其中一个类库,会弹出”对象浏览器”窗口,其中一层层列出了类库->各类库所包含的名称空间->相关名称空间包含的类。
*强调一点:不同的项目模板本质上建了项目之后相应地引用了不同技术(比如winform和WPF)所需要的类库。
如果我们除了模板引用的类库之外还想要引用其他类库怎么办呢?日常工作中对类库的引用就两种方式:
第一种:是对编译好的DLL直接引用,这种引用我们叫黑盒引用,因为我们没有DLL的源代码;
第二种:我们有类库的源代码,然后我们对源代码进行引用,源代码是放在项目里面,这叫做项目引用,或者叫白盒引用,能够看到源代码的。
两种引用各有特点。需要注意的是当把DLL拿来之后一定要配一个说明文档,不然用处不大,因为黑盒引用不知道源代码就不清楚该DLL有什么名称空间和类就无法使用。在那里添加类库?在解决方案->引用->右键->添加引用->右下角”浏览”添加本地DLL,这样就把下载来的类库引用程序了,然后就可以对着说明文档使用类库。(同样可以使用上述方法查看这个类库有多少个命名空间和相关的类)
*黑盒引用存在的问题,若代码存在错误,无法修改,还能告诉制作类库的人让他改了,再编译出DLL再发给我才行。另一方面,我的程序对这个引入的类库有了依赖性,即它的类库有问题我的程序也会有问题,这就是依赖,而在类的级别也会有依赖性,即我的类:如C#程序体都包含在 class Program中,调用了该类库的类,这两个类之间也有依赖关系,连为一体,一方出错,双方都错。*写程序时一定要小心这个依赖关系。这个依赖关系大概有5,6种有的依赖关系很强,有的依赖关系很弱,我们尽量使用比较弱的依赖关系,这样的话,我的程序就不至于出现某个底层的类出现问题我的上层所有的程序都不能工作。
解决办法之一,弱的依赖关系:比如可以暂时先用一个相似的类替换该出错的DLL,再继续修成程序,等该DLL修改好再继续使用该类库。怎么安排?这是比较高级的内容。
可以发现DLL的文档就是MSDN文档的缩影:MSDN里面有非常庞大的类库的文档,在里面可以查找每一个类的信息,包括方法、属性、事件等。
想法:本来控制台程序是不能显示窗口的,但是如果引入相关类,就变得可以显示窗口了。解决方案->引用->右键添加引用->程序集选项卡里搜索System.Windows.Forms,添加该类库,则该类库就是我们程序的一部分了,可以*引用,引用DLL类前,如上面所说的要先,写命名空间,方式发生冲突:Using System.Windows.Forms;再引用Form类就没问题了。
使用新潮技术(NuGet)来解决比较复杂的依赖关系问题,程序和类库有一定的依赖,底层的库是引用不了上层的库。因为上层的类库需要许多底层的类库支持才能运行,但凡缺少一个底层的类库没有引用进来,上层的类库都不能使用。引用的时候硬盘里面再有重名的类库或者版本不同的这样引用起来很可能在程序中引入一些非常难以排除的错误。因为这时候你只有DLL,没有源代码,几乎可以说是“蒙着眼睛引用类库”这是很危险的!特别是对于大型的项目。
解决方法:以一个类库包的形式放在网上,客户要用我敲一个命令一组类库都包含到项目里面去了,不用手动的添加引用类库,这样就非常安全,高效,这就是NuGet技术:解决方案->引用->管理NuGet程序包,在这里面搜索相关类库集合而成的包,安装它,就会在我们项目的引用里自动添加相关的类库,而且新添加的类库都是由NuGet管理不用担心,版本啊,缺少某个类库之类的问题了,十分方便。*总结:用NuGet去引用网上一些非常好的类库。
2.2、项目引用(白盒引用,有源代码)
自己写类的时候有命名空间是为了让别人引用更加方便。一个项目隶属了多个solution(解决方案)这就项目的重用,当我们拥有别人类库的源代码,可以在解决方案右击->添加->已有项,这样就可以把别人的项目文件添加到我们的程序里了,此时在右击引用->添加,在解决方案选项卡就可以看到我们添加的别人项目里的类库了,选择添加即可开始引用该项目的类库。可见同一个解决方案下的不同项目要通过上面的方法才可以使用彼此的类库。
Debug修的,排错的找的是Root cause!不要在补丁上打补丁,不在问题根源修复只会越弄越差。
这就是白盒引用。
2.3、建立自己的类库项目
右击解决方案->添加->新建项目->选择类库(class library)项目,class library它不是可执行的文件,它编译出来的结果就是DLL(类库),在生成的CS文件里面进行类库相关类与方法的编写。在创建的类库项目上右击->生成就会在该项目本地源码文件夹bin->debug文件夹里面生成DLL(类库文件)这样附上使用说明就可以传播出去了。
3、依赖关系
类和类之间是有依赖关系的,类库和类库之间也是由依赖关系的,那么如果底层的类或者类库有问题,那么上层的类或者类库工作也会不正常,所以依赖关系(也叫耦合关系)是非常重要的。
3.1、类(或对象)之间的耦合关系
3.2、优秀的程序追求”高内聚,低耦合”(教学程序往往会违背这个原则)
高内聚:指一些数据一些功能该属于哪些类就放到哪些类里面去,要精确的放在这些类里面去,这就叫高内聚;
低耦合:类与类之间的关系尽可能的低,尽可能的松,就叫低耦合。
类库的设计也是这个原则,一些类该放到哪些类库里面就放到哪些类库里面,不要乱放,类库与类库之间的关系也尽量是低耦合的,低依赖的。这样程序结构才会非常清晰。
3.3、UML(通用建模语言)类图:
展现类与类之间的关系。
4、排除错误
4.1、仔细阅读编译器的报错。
4.2、MSDN文档与搜索引擎结合。
当你看到一大片错误的时候不见得真的有这么多错误,有的时候就是一个很小的错误就造成这么多错误,比如:中文的标点符号。(实际上编译器是有一定智能的如果语句正确,会高亮显示);真正难排除的错误是编译器认为是对的,但是运行会出错这就是逻辑错误,需要一步步debug来解决。