------- Windows Phone 7手机开发、.Net培训、期待与您交流! -------
命名空间
在程序中,我们都需要声明类。如果需要声明的类较多时,类名一不小心就会重复,给我们带来麻烦。而且在多人共同开发项目时,很容易出现使用同一个名字命名不同的类。当把程序集成到一块时,就会出现各种错误。命名空间的出现解决了这些问题。命名空间的作用是,在它内部声明的名称不会与在它外部声明的相同名称冲突。本章将为大家详细讲解C#语言的命名空间。
什么是命名空间
命名空间(namespace)是定义了一个声明区域,它提供了将一组名称和另一组名称进行区分的方法。命名空间具有4个用途:
一是组织大型代码项目。
二是使用.运算符将它们分隔。
三是using指令不必为每个类指定命名空间的名称。
四是global命名空间是.NET Framework应用程序的“根”命名空间,global::System始终引用.NET Framework中的System命名空间。
一个C#程序可以不包括任何命名空间,也可以包含一个或多个命名空间。命名空间可以由系统提供,如.NET Framework类库,也可以由开发人员自己定义。
注意:对于一个C#源文件而言,不管开发人员是否声明了命名空间,编译器都为该文件添加一个默认的命名空间。
声明命名空间
命名空间在使用的时候,也需要声明。然后,再将相关的类写到该空间中。声明命名空间:
namespace qualified-identifier
{
body
[;]
}
qualified-identifier表示命名空间的名称,该名称必须惟一;body表示该命名空间的内容主体(该部分是不可缺少的);分号(;)是一个可选项。一旦声明了一个命名空间之后,该命名空间中的主体源代码将在该命名空间中进行编译。
下面声明一个名称为Chapter7的命名空间。
namespace Chapter7 //声明一个命名空间Chapter7
{
}
注意:命名空间隐式地为public,不能被修改,而且在命名空间的声明中不能包含任何访问修饰符。命名空间的名称可以是单个标识符,也可以是由“.”(点号)分隔的标识符序列。
下面声明一个名称为Chapter7.Test的命名空间。
namespace Chapter7.Test //声明一个命名空间Chapter7.Test
{
}
带“.”(点号)的命名空间实际上是一个嵌套命名空间,
即在一个命名空间中声明另外一个命名空间。
下面声明一个名称为Chapter7.Test的命名空间,并在该命名空间中声明一个嵌套的、名称为Test的命名空间。
namespace Chapter7.Test //声明一个命名空间Chapter7.Test
{
namespace Test
//命名空间Chapter7.Test中声明一个嵌套的命名空间Test
{
}
}
注意:与上面是等效的。
一个命名空间可以包含多种类型,具体包括6种类型:嵌套的命名空间、类、接口、结构、枚举、委托。
下面在ConsoleApplication命名空间中声明一个类Program,并且打印输出字符串“Hello”。
namespace ConsoleApplication
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello");
Console.ReadLine();
}
}
}
命名空间中的内容是可扩充的。但是同一个命名空间下,不能存在相同的名称的类型,否则会产生编译错误。命名空间声明好了以后,访问它的内容就要用到点号运算符、双冒号运算符等,下面我们来学习命名空间的使用方法。
.(点号)运算符
在同一个命名空间中,各个类可以互相调用。如果在不同的空间中,就需要在调用的类之前添加对应的命名空间名称加点号。
下面使用.运算符访问System命名空间下的Int32类型,并声明该类型的i变量。
namespace ConsoleApplication
{
class Program
{
static void Main(string[] args)
{
System.Int32 i;
i = 10;
Console.WriteLine(i);
Console.ReadKey();
}
}
}
下面程序中在ConsoleApplication命名空间中声明三个类:Class1、Class2和Program。然后使用.运算符访问ConsoleApplication命名空间下的Class1和Class2类。
namespace ConsoleApplication
{
class Class1
{ }
class Class2
{ }
class Program
{
static void Main(string[] args)
{
ConsoleApplication.Class1 c1 = new ConsoleApplication.Class1();
ConsoleApplication.Class2 c2 = new ConsoleApplication.Class2();
Console.WriteLine(c1);
Console.WriteLine(c2);
Console.ReadKey();
}
}
}
“ConsoleApplication.Class1 c1 = new ConsoleApplication.Class1();”和“ConsoleApplication.Class2 c2 = new ConsoleApplication.Class2();”语句创建了类型分别为Class1和Class2的实例c1和c2,并为它们分配了内存。
::(双冒号)运算符
用户在写程序时,可能会使用与系统封装的类相同的名称命名一个类。调用的时候就会出现问题。因此可以使用双冒号(::)运算符在指定的命名空间中查找标识符,就可以精确地定位需要访问的类。双冒号运算符通常放置在两个标识符之间。
下面程序中的Test命名空间中有个Class1类,空间中也有Class1类,当同时引用这两个命名空间后,就要使用::运算符限定命名空间查找Class1类。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using T = Test;
using CA = ConsoleApplication;
namespace Test
{
class Class1
{
public void Print()
{
Console.WriteLine("Test 命名空间的方法 Print() ");
}
}
}
namespace ConsoleApplication
{
class Class1
{
public void Print()
{
Console.WriteLine("ConsoleApplication 命名空间的方法 Print() ");
}
}
class Program
{
static void Main(string[] args)
{
T::Class1 c1 = new T::Class1();
c1.Print();
CA::Class1 c2 = new CA::Class1();
c2.Print();
Console.ReadKey();
}
}
}
在本例中,Test命名空间和ConsoleApplication命名空间中都有类Class1。在类Program中使用Class1类时就要限定命名空间。如果不使用双冒号运算符限定命名空间,编译时就会出现错误,错误信息为:”Class1”是” ConsoleApplication.Class1”和”Test.Class1”之间的不明确的引用
注意:双冒号前面写指定的命名空间,即在该命名空间中查找。也可以写global,是指从最顶层开始向下的命名空间中查找。
using指令
在不同的空间中调用类时,需要在调用的类之前添加对应的命名空间名称加点号。如果需要频繁地使用这个命名空间中的代码,就可以使用using指令导入这个命名空间,简化了代码。当using关键字作为指令时,它用于为命名空间或类型创建别名或导入其他命名空间中定义的类型。
导入命名空间
在开发过程中,如果要经常性地使用某个命名空间中的代码,每次都加上类型的完全限定符,会很繁琐。因此,我们可以使用using指令将该命名空间中所包含的类型导入到指定的程序体或文件中。使该程序体或文件中的代码可以直接访问该命名空间中的类型,而不需要加上类型的完全限定符(如命名空间的名称)。
using 表示被导入的命名空间。
下面使用using指令导入Test命名空间,然后直接访问它的成员:Class1类和Class2类。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Test;
namespace Test
{
class Class1
{ }
class Class2
{ }
}
namespace ConsoleApplication
{
class Program
{
static void Main(string[] args)
{
Class1 c1 = new Class1(); // Test.Class1
Class2 c2 = new Class2(); // Test.Class1
Console.WriteLine("Class1 类的实例 c1 ");
Console.WriteLine("Class2 类的实例 c2 ");
Console.ReadKey();
}
}
}
注意:导入示例Test空间之后,如果要访问该命名空间中的成员,不再需要添加该命名空间的限定符。上述代码中的Class1在语义上和示例Test.Class1等效。using指令在导入命名空间时,不导入它所包含的嵌套命名空间。
下面使用using指令导入Csharp.Test命名空间。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Csharp.Test;
namespace Csharp.Test
{
namespace Test
{
class Class1
{ }
}
class Class2
{ }
}
namespace ConsoleApplication
{
class Program
{
static void Main(string[] args)
{
//Test.Class1 c1 = new Test.Class1();
//Console.WriteLine(c1);
Class2 c2 = new Class2();
Console.WriteLine(c2);
Console.ReadKey();
}
}
}
“using Csharp.Test;”语句只导入了Csharp.Test命名空间,但是不导入它的嵌套命名空间Test。因此,Test.A语句中的Test是未知的,导致编译错误。
创建命名空间或类型别名
using指令还可以为一个命名空间或类型创建特定的、简单的别名,使得通过该别名也可以引用该命名空间或类型。
下面使用using指令为Csharp.Test命名空间创建别名Cs,然后通过Cs别名访问它的成员:Class1和Class2。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Cs = Csharp.Test;
namespace Csharp.Test
{
class Class1
{ }
class Class2
{ }
}
namespace ConsoleApplication
{
class Program
{
static void Main(string[] args)
{
Cs.Class1 c1 = new Cs.Class1();
Cs.Class2 c2 = new Cs.Class2();
Console.WriteLine(c1);
Console.WriteLine(c2);
Console.ReadKey();
}
}
}
“Cs.Class1 c1 = new Cs.Class1();”和“Cs.Class2 c2 = new Cs.Class2();”语句创建了类型分别为Class1和Class2的实例c1和c2,并为它们分配了内存。
下面使用using指令为Csharp.Test命名空间中的Class1类型创建别名A,然后通过A别名访问Csharp.Test.Class1类。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Cs = Csharp.Test; //使用using指令创建命名空间的别名
using A = Csharp.Test.Class1; //使用using指令创建别名
namespace Csharp.Test
{
class Class1
{ }
class Class2
{ }
}
namespace ConsoleApplication
{
class Program
{
static void Main(string[] args)
{
A c1 = new A(); //实例化类
Cs.Class2 c2 = new Cs.Class2();
Console.WriteLine(c1);
Console.WriteLine(c2);
Console.ReadKey();
}
}
}
注意:新创建的别名在其所在的命名空间中也必须唯一,否则产生编译错误。