在继续学习之前,应该了解另一个比较重要的主题——命名空间。它们是.NET中提供应用程序代码容器的方式,这样就可以唯一的标识代码及其内容。命名空间也用作.NET Framework中给项分类的一种方式。大多数项都是类型定义,例如System.Int32等。
默认情况下,C#代码包含在全局命名空间中。这表示对于包含在这段代码中的项,只要按照名称进行引用,就可以由全局命名空间中的其他代码访问它们。可以使用namespace关键字位花括号中的代码块显示定义命名空间。如果在该命名空间代码的外部使用命名空间中的名称,就必须写出该命名空间中的限定名称。
限定名称包括它所有的继承信息。基本上,这意味着,如果一个命名空间中的代码要使用另一个命名空间中定义的名称,就必须包括对该命名空间的引用。限定名称在不同的命名空间级别之间使用据点字符(.)。
例如:
namespace LevelOne
{
//code in LevelOne namespace
//name "NameOne" defined
}
//code in global namespace
这段代码定义了一个命名空间LevelOne,以及该命名空间中的一个名称NameOne。在命名空间LevelOne中编写的代码可以使用NameOne来引用该名称,不需要任何分类信息。但全局命名空间中的代码必须使用分类名称LevelOne.NameOne来引用这个名称。
在命名空间中,使用关键字namespace还可以定义嵌套的命名空间。嵌套的命名空间通过其层次结构来引用,并使用据点区分层次结构的层次。这最好用一个例子来说明。考虑下面的命名空间:
namespace LevelOne
{
//code in LevelOne namespace
namespace LevelTwo
{
//code in LevelOne.LevelTwo namespace
//name "NameTwo" defined
}
}
//code in global namespace
在全局命名空间中NameTwo必须引用为LevelOne.LevelTwo.NameTwo,在LevelOne命名空间中,则可以引用位LevelTwo.NameTwo,在LevelOne.LevelTwo命名空间中,则可以引用为NameTwo。
要注意的是,名称由命名空间唯一定义的。可以在LevelOne和LevelTwo命名空间中定义名称NameThree:
namespace LevelOne
{
//name "NameThree" defined
namespace LevelTwo
{
//name "NameThree" defined
}
}
这里定义了两个互不干扰的NameThree,分别用LevelOne.NameThree和LevelOne.LevelTwo.NameThree访问。
创建了命名空间后,就可以使用using语句简化对它们包含的名称的访问。实际上,using语句的意思是“我们需要这个命名空间中的名称,所以不要每次总是要求对它们分类”。例如,在下面的代码中,LevelOne命名空间中的代码可以访问LevelOne.LevelTwo命名空间中的名称,而无需分类:
namespace LevelOne
{
using LevelTwo;
namespace LevelTwo
{
//name "NameTwo" defined
}
}
LevelOne命名空间中的代码现在可以直接使用NameTwo引用LevelTwo.NameTwo。
有时,与上面的NameThree示例一样,不同的命名空间中的相同名称会产生冲突,使系统崩溃(此时代码不能通过编译)。此时,可以为命名空间提供一个别名,作为using语句的一部分:
namespace LevelOne
{
using LT = LevelTwo;
//name "NameThree" defined
namespace LevelTwo
{
//name "NameThree" defined
}
}
LevelOne命名空间中的代码可以把LevelOne.NameThree引用位NameThree,把LevelOne.LevelTwo.NameThree引用为LT.NameThree。
using语句可以应用到包含它们的命名空间,以及该命名空间中包含的嵌套命名空间中。在上面的代码中,全局命名空间不能直接使用LT.NameThree。但如果using语句声明如下:
using LT = LevelOne.LevelTwo;
namespace LevelOne
{
//name "NameThree" defined
namespace LevelTwo
{
//name "NameThree" defined
}
}
这样全局命名空间中的代码和LevelOne命名空间就可以使用LT.NameThree。
这里有一点要注意:using语句本身不能访问令一个命名空间中的名称。除非命名空间中的代码以某种方式链接到项目上,或者代码是在该项目的源文件中定义的,或在链接到该项目的其他代码中定义的,否则就不能访问其中包含的名称。另外,如果包含命名空间的代码链接到项目上,无论是否使用using,都可以访问其中包含的名称。using语句便于我们访问这些名称,减少代码量,使之更合理。
再看看以前我们ConsoleApplication1中的代码,下面的代码被应用到命名空间上:
using System;
using System.Collections.Generic;
using System.Text;
namespace ConsoleAppcation1
{
...
}
using指令块中的3行代码使用using声明:在这段C#代码中使用Systen、System.Collections.Generic和System.Text命名空间,它们可以在该文件的所有命名空间中访问,无需分类。System命名空间是.NET Framework应用程序的根命名空间,提供了控制台应用程序所需要的所有基本功能。其他两个命名空间常常用于控制台应用程序,所以该程序包含了这3行代码。
最后,为应用程序代码本身声明了一个命名空间ConsoleAppcation1。