C#学习笔记(四)

来源:互联网 发布:windows xp 纯净版下载 编辑:程序博客网 时间:2024/05/30 04:07
第4讲命名空间
 现在来讲一下命名空间,通常一个软件项目包含类可能成千上万,如果2个以上的类有相同的名称时该怎么办呢?在C#中您可以使用命名空间就是namespace来解决命名冲突的问题,C#中命名空间其实就类似于Java中的Package就是包,在C#中命名空间可以用来定义C#类的范围。
  PPT:.NET Framework类库由命名空间组成。每个命名空间都包含可在程序中使用的类型:类,结构,枚举,委托和接口。
  下面我们来做个例子来看看如何声明namespace,创建一个namesapce.cs文件,代码如下:
  1. using System;
  2. //使用namespace关键字,后面是命名空间的名称CG
  3. //在大括号之间的所有代码都属于这CG命名空间
  4. namespace CG
  5. {
  6.     //声明一个类Test
  7.     class Test
  8.     {
  9.         static void Main()
  10.         {
  11.             //打印一行My name is CG
  12.             Console.WriteLine("My name is CG");
  13.         }
  14.     }
  15. }
保存文件后进行编译执行,效果如下:

  屏幕上打印出了我们刚才输入的这行字符,看我们刚才的代码。
  在这个例子中,在CG这个命名空间之下声明了一个类,当然这个类很简单,只是在屏幕上打印一行字。我们当然可以在这个命名空间下声明很多个类,去实现不同的功能。我们接下来把输出语句放到别的命名空间下,下面我们来试一下。我们首先在原代码中声明另一个命名空间,这个命名空间的名字叫A。A地下声明一个类,详细请看代码:
  1. using System;
  2. //使用namespace关键字,后面是命名空间的名称CG
  3. //在大括号之间的所有代码都属于这CG命名空间
  4. namespace CG
  5. {
  6.     //声明一个类Test
  7.     class Test
  8.     {
  9.         static void Main()
  10.         {
  11.             //我们在入口函数里调用A命名空间里的PrintName类底下的intro这个函数
  12.             //首先声明PrintName类,前面要加上命名空间的名称
  13.             //并且对其初始化
  14.             A.PrintName a= new A.PrintName();
  15.             //可以使用a实例中的intro函数了
  16.             a.intro();
  17.         }
  18.     }
  19. }
  20. //声明另外一个命名空间A
  21. namespace A
  22. {
  23.     //声明一个类PrintName
  24.     public class PrintName
  25.     { 
  26.         //写个输出的函数
  27.         public void intro()
  28.         {
  29.             Console.WriteLine("My name is A");
  30.         }
  31.     }
  32. }
好,我们进行编译执行程序,效果如下:

屏幕上成功打印了My name is A,也就是说我们调用了A这个命名空间PrintName类底下的intro这个函数。当我们在CG命名空间下想使用A命名空间下的函数,(A.PrintName)则必须要在它的类前面加上A这个命名空间的前缀,才能去使用它。
  下面我们再声明另外一个命名空间B,它里面的代码和A命名空间里的代码完全一样,为了以示区别,把输出语句改成My name is B,入口函数也稍做改动,代码如下:
  1. using System;
  2. namespace CG
  3. {
  4.     class Test
  5.     {
  6.         static void Main()
  7.         {
  8.             A.PrintName a= new A.PrintName();
  9.             a.intro();
  10.             //初始化B命名空间下的PrintName类
  11.             B.PrintName b = new B.PrintName();
  12.             //调用intro函数
  13.             b.intro();
  14.         }
  15.     }
  16. }
  17. //声明另外一个命名空间A
  18. namespace A
  19. {
  20.     //声明一个类PrintName
  21.     public class PrintName
  22.     { 
  23.         //写个输出的函数
  24.         public void intro()
  25.         {
  26.             Console.WriteLine("My name is A");
  27.         }
  28.     }
  29. }
  30. //再声明另外一个命名空间B
  31. namespace B
  32. {
  33.     //声明一个类PrintName
  34.     public class PrintName
  35.     {
  36.         //写个输出的函数
  37.         public void intro()
  38.         {
  39.             Console.WriteLine("My name is B");
  40.         }
  41.     }
  42. }
进行编译执行查看效果,如图:

在这里呢,分别调用了A命名空间里的intro函数和B命名空间里的intro函数。而且,它们底下的类PrintName和类下的函数intro都是一模一样的。但是通过了它们的命名空间的前缀,将它们区分开来,也就是说,在C#中只要使用了命名空间就不必担心你写的类会跟其他人所写的类有相同的名称。
  下面我们来看一下使用命名空间的好处:
  PPT:1.代码可以分布在多个文件中
       2.命名空间具有扩展性
       3.可以堆砌出层次式的类组织结构
  我们先来看一下第三点,命名空间和类一样,允许采用嵌套的结构,一个命名空间可以包含其他命名空间,形成层次式结构,以更容易分组,管理。好,我们再修改下代码,在A和B命名空间上嵌套一个命名空间A,把A和B命名空间的名称改为A1,A2。代码如下:
  1. using System;
  2. namespace CG
  3. {
  4.     class Test
  5.     {
  6.         static void Main()
  7.         {
  8.             //访问的命名路径名要完整
  9.             A.A1.PrintName a = new A.A1.PrintName();
  10.             a.intro();
  11.             A.A2.PrintName b = new A.A2.PrintName();
  12.             b.intro();
  13.         }
  14.     }
  15. }
  16. namespace A
  17. {
  18.     namespace A1
  19.     {
  20.         public class PrintName
  21.         {
  22.             public void intro()
  23.             {
  24.                 Console.WriteLine("My name is A");
  25.             }
  26.         }
  27.     }
  28.     namespace A2
  29.     {
  30.         public class PrintName
  31.         {
  32.             public void intro()
  33.             {
  34.                 Console.WriteLine("My name is B");
  35.             }
  36.         }
  37.     }
  38. }
我们再编译执行后效果也是一样的。A命名空间下有A1和A2这2个命名空间,要找到他们的类和访问他们的函数时,就必须在初始化实例的时候需要给出全路径名(A.A1.PrintName a = new A.A1.PrintName();),这样呢就形成了层次式的结构,以更容易的分组和管理。
  我们再来看下使用命名空间的好处。
第一点:代码可以分布在多个文件中。在同一个命名空间下的不同类可以分布在多个文件中存储,不过在使用嵌套类的时候要小心,他们必须在同一个文件中。不可以跨不同文件存在,下面我们把代码再修改下。把这个类移植到另外一个文件中,我们新建一个文件,名字叫PrintName.cs。里面的命名空间名也是CG,namespace.cs和printName.cs代码如下:
PrintName.cs
  1. using System;
  2. namespace CG
  3. {
  4.     public class PrintName
  5.     {
  6.         public void intro()
  7.         {
  8.             Console.WriteLine("My name is A");
  9.         }
  10.     }
  11. }
namespace.cs
  1. using System;
  2. namespace CG
  3. {
  4.     class Test
  5.     {
  6.         static void Main()
  7.         {
  8.             PrintName a = new PrintName();
  9.             a.intro();
  10.         }
  11.     }
  12. }
这个时候,我们要对这2个文件进行同时编译,csc时后面跟2个文件名,中间用空格隔开,然后执行namespace,效果如图所示:

好,结果出来了。我们回头看一下代码。我们在主文件中(namespace.cs)中使用了CG这个命名空间,在PrintName文件中也使用了CG这个命名空间。换句话说,相同的命名空间可以分布在不同的文件之中,而在调用的时候,不需要再次去引用这个类的命名空间的前缀了,这样呢使我们的管理变得方便很多。
  在实际的编程中,如果程序较大而且会频繁的更新,则需要把程序分布在不同的文件之中。就比如我们玩网络游戏,一个游戏的大小有1G,而且一个星期就要更新一次,如果游戏的程序放在一个文件之中,那通过网络更新的时候我想再强健的网络也会受不了。但如果把一个程序分布在多个文件之中,哪个文件更改就下载哪个文件,这样就不会存在网络问题了。
  在C#中,你可以把类库编译成dll文件,供程序调用。下面我们来试一下把PrintName做成dll文件。进入命令行窗口,进入到我们放PrintName文件的地方,输入csc /target:library PrintName.cs,如图所示:

我们去看看放置PrintName.cs文件下,已经产生了一个PrintName.dll的文件了。如图所示:

/target:library 代表着把cs文件编译成dll文件,接下来我们把主文件和dll文件进行相关联,并编译,还是使用csc命令,输入csc /reference:PrintName.dll namespace.cs,这里的reference表示跟某个dll进行关联。关联后然后我们再执行namespace程序。如图所示:

屏幕上正常输出了My name is A。好,接下来我们把程序稍改一下,就当这个游戏需要更新了。我们把PrintName文件中的输出语句内容改下,改成My name is B。然后我们对这个PrintName文件重新编译dll,输入csc /target:library PrintName.cs,编译成功后我们直接执行namespace看看效果如何:

好,我们看到屏幕的输出改变了,它由原来的My name is A改成了My name is B,也就是说我们不需要再编译exe文件,而只编译它所调用到的dll文件,这使得我们对程序作出修改时不至于重新编译整个程序,这样做的好处是显而易见的。
  我们现在来看一下第二点:命名空间具有扩展性。
  你可以在命名空间中增加新类,而不影响其他已存在于此命名空间的类,使得设计灵活性更高。 
  下面我们来讲一下别名(Alias)。
  PPT:使用using前缀指令可以有效地解决命名空间冲突问题,不过它还有一个特性,使用using加上简称,可以让定义在其他命名空间的类型更容易使用,大多是应用在使用简短的名称来代替欲使用的类。我们看下下面的代码:
  1. using System;
  2. namespace CG
  3. {
  4.     class Test
  5.     {
  6.         static void Main()
  7.         {
  8.             //这个前缀十分淤长
  9.             ParentNameSpace.ChildNameSpaces.PrintName a = new ParentNameSpace.ChildNameSpaces.PrintName();
  10.             a.intro();
  11.         }
  12.     }
  13. }
  14. //这里使用了嵌套的命名空间
  15. namespace ParentNameSpace
  16. {
  17.     namespace ChildNameSpaces
  18.     {
  19.         public class PrintName
  20.         {
  21.             public void intro()
  22.             {
  23.                 Console.WriteLine("My name is A");
  24.             }
  25.         }
  26.     }
  27. }

我们看到在Main函数中初始化类的时候,前面的命名空间十分的淤长,看上去很不爽。下面我们用一下命名空间的别名来改写这段代码。代码如下:
  1. using System;
  2. //起个别名A代替ParentNameSpace.ChildNameSpaces
  3. using A = ParentNameSpace.ChildNameSpaces;
  4. namespace CG
  5. {
  6.     class Test
  7.     {
  8.         static void Main()
  9.         {
  10.             //别名A代替ParentNameSpace.ChildNameSpaces
  11.             A.PrintName a = new A.PrintName();
  12.             a.intro();
  13.         }
  14.     }
  15. }
  16. //这里使用了嵌套的命名空间
  17. namespace ParentNameSpace
  18. {
  19.     namespace ChildNameSpaces
  20.     {
  21.         public class PrintName
  22.         {
  23.             public void intro()
  24.             {
  25.                 Console.WriteLine("My name is A");
  26.             }
  27.         }
  28.     }
  29. }
好,我们编译执行一下代码,程序运行正常!