C#中使用namespace关键字定义命名空间,命名空间类似我们电脑文件资源管理器中的文件夹,可自由命名且具有层级,命名空间中的各个类就像文件夹中的文件,通过各种命名及划分层级来分类存放
命名空间通过关键字namespace定义,使用"."或者{}包含来定义嵌套的命名空间,如下面两段代码在语义上是等价的:
namespace Outer.Middle.Inner
{
class Class1 { }
class Class2 { }
}
namespace Outer
{
namespace Middle
{
namespace Inner
{
class Class1 { }
class Class2 { }
}
}
}
如果类型没有在任何命名空间中定义,则它存在于全局命名空间. 全局命名空间包含了顶层命名空间,如上例中的Outer命名空间
using指令用于导入命名空间,可以避免使用完全限定名称来指代某种类型.以下例子导入了上述例子中的Outer.Middle.Inner命名空间:
using Outer.Middle.Inner;
class Test
{
static void Main()
{
Class1 c1; //此处不需要一层层指定Class1的命名空间,因为已经通过using引入了
}
}
使用using static可以引用命名空间中的静态成员,包括字段,属性及嵌套类型.如下例中我们引用Console类的静态成员后可直接调用WriteLine方法:
using static System.Console;
WriteLine("Hello, World!");
注意using static指令只能用于类型,不能用于命名空间(将产生一个编译错误)
using static除了能导入静态成员外还能导入枚举类型:
using static System.Windows.Visibility;
var textBox = new TextBox{ Visibility = Hidden}; //此处不需要指定Visibility.Hidden
外层命名空间中声明的名称能够直接在内层命名空间中使用
namespace Outer
{
public class OuterClass { }
namespace Middle
{
namespace Inner
{
class Class1:OuterClass { }
}
}
}
命名空间分层结构中不同分支中的类型需要使用部分限定名称
namespace Outer
{
public class OuterClass { }
namespace Middle
{
namespace Inner
{
class Class1:OuterClass { }
}
namespace Inner2
{
class Class2:Inner.Class1 { } //此处不能直接使用Class1
}
}
}
如果同一类型名称同时出现在外层和内层命名空间中,则内层名称优先.如果要使用外层类型,必须使用它的完全限定名称:
namespace Outer
{
public class One { }
namespace Inner
{
class One { }
class Test
{
One inner;// = Outer.Inner.One
Outer.One outer; // =Outer.One
}
}
}
所有类型名称在编译时都会转化为完全限定名称.中间语言(IL)代码不包含非限定名称和部分限定名称.
只要命名空间中的类型名称不冲突就可以重复声明同一个命名空间:
namespace Outer
{
class Class1 { }
}
namespace Outer
{
class Class2 { }
}
上述示例和在Outer命名空间中同时定义Class1和Class2语义上是一样的,上面两个类也可以分别定义在两个不同的源文件,编译到不同的程序集中去.
导入命名空间可能会导致类型名称的冲突,这时我们可以为导入的类型或者命名空间创建别名,如下:
using Assembly2 =System.Reflection.Assembly; //给命名空间中的指定类型创建别名
class Program
{
Assembly2 asm; //= System.Reflection.Assembly
}
using R = System.Reflection; //给整个命名空间创建别名
class Program
{
R.Assembly asm; //= System.Reflection.Assembly
}
之前提到,由于内层命名空间中的名称优先级更高会隐藏外层命名空间中的名称.有时即使使用类型的完全限定名称也无法解决冲突,如下示例:
namespace N
{
class A
{
A.B b; //此处虽然使用完全限定名称,但还是会拿到嵌套类B的实例,而不是A命名空间下的类B
class B { }
}
}
namespace A
{
class B { }
}
要解决这样的冲突,可以使用全局命名空间global来限定命名空间中的名称:
namespace N
{
class A
{
global::A.B b; //通过global限定全局命名空间下的A命名空间中的类B
class B { }
}
}
namespace A
{
class B { }
}