关于c#:命名空间

命名空间与类型有些类似,在类型中能够申明诸多成员:字段,属性,办法,而在命名空间中能够申明:类,接口

命名空间属于逻辑组合,用来对类型的性能进行逻辑分组

成员依据相关性能够将name, age, sex成员定义到Person类型中
类型能够把Dog, Cat类型定义到名为Animal的命名空间里

申明命名空间的构造
namespace 名字 { }
命名空间不能有修饰符如拜访修饰符
//谬误,不能应用修饰符
private namespace 名字 { }
申明Animal命名空间
namespace Animal { }

*命名空间的命名规定可参考变量名(可查看往期文章变量和常量)

命名空间中不能蕴含成员: 字段,属性,办法
namespace Animal
{
    private int id; //谬误
    public int Id { get; set; } //谬误
    private void Test() { } //谬误
}
类型名必须惟一,同一个命名空间中无奈定义同样的类型
namespace Animal
{
    //正确
    class Dog { }

    //谬误,命名空间 Animal中曾经蕴含了Dog的定义
    class Dog { }
}

*如果未给类型显示提供命名空间,该类型将会被编译器默认放到一个没有名称的全局命名空间(global namespace)中

//正确
class Dog { }
//谬误,命名空间 global namespace中曾经蕴含了Dog的定义
class Dog { }

*就像类型中无奈定义多个雷同名称的成员一样,类型名也须要具备唯一性

命名空间的另一个作用便是进步类型名的唯一性,无奈在同一个名称空间下定义雷同的类型,实质起因也是类型名需惟一

所以能够写出上面这样的代码

//正确
class Dog { }
namespace Animal
{
    //正确,属于不同命名空间
    class Dog { }
}

起因: 两个Dog类型分属不同的名称空间,属于全局命名空间的Dog类型名:Dog,属于Animal命名空间的Dog类型名: Animal.Dog

拜访不同命名空间中的类型(全局命名空间类型除外)须要应用类型限定名,同一个命名空间下则不须要

namespace Animal
{
    class Dog
    {
        void Test()
        {
         //正确
         Dog dog = new Dog();
        }
    }
}
namespace A
{
    class Person
    {
        void Test()
        {
            //谬误,未找到类型名
            Dog dog = new Dog();
            //正确
            Animal.Dog dog = new Animal.Dog();
        }
    }
}

然而这样的代码过于繁琐,同时也升高了代码的可读性

能够应用using指令简化代码

using Animal;
namespace Animal
{
    class Dog { }
}
namespace A
{
    class Person
    {
        void Test()
        {
            //正确
            Animal.Dog dog = new Animal.Dog();
            //正确
            Dog dog = new Dog();
        }
    }
}

using指令注意事项

namespace A
{
    //正确
    using Animal;
    class Person { }
}
//谬误用法
namespace A
{
    class Person { }
    //谬误,using指令必须在命名空间中定义的所有其它元素之前
    using Animal;
    class Person { }
}

为什么以下代码会报错呢

//谬误
using Animal;
namespace Animal { }

因为未显示指定命名空间的类型默认增加到全局没有名字的命名空间中
所以上述代码相当于

//global只是举例
namespace global
{
    class Dog { }

    //谬误,using指令必须在命名空间中定义的所有其它元素之前
    using Animal;
    namespace Animal { }
}

*这便是为什么所有using都须要写在最后面的起因了

能够定义同名的命名空间
namespace Animal
{
    class Dog { }
}
namespace Animal
{
    class Cat { }
}

相当于是这样的

namespace Animal
{
    class Dog { }
    class Cat { }
}
命名空间能够嵌套
namespace A
{
    namespace B
    {
        namespace C
        {
        }
    }
}

也能够从外到内顺次递进,应用句点分隔每个命名空间名称的形式改写简化代码

namespace A.B.C { }
不明确的援用

如果不同的命名空间中定义了雷同的类型,这时在应用该类型的时候便会呈现歧义,编译器报错”类型”是不明确的援用

namespace A
{
    //命名空间A定义Bird类型
    class Bird { }
}
namespace B
{
    //命名空间B定义Bird类型
    class Bird { }
}
//只增加using A或者using B是正确的
namespace C
{
    using A;
    class Person
    {
        void Test()
        {
            //正确
            Bird bird = new Bird();
        }
    }
}

同时应用两个命名空间下的雷同类型名便会呈现歧义

//若须要同时应用两个类型
namespace C
{
    using A;
    using B;
    class Person
    {
        void Test()
        {
            //谬误Bird 是A.Bird 和B.Bird 之间不明确的援用
            Bird bird = new Bird();
        }
    }
}
打消歧义性办法
  • 应用类型的齐全限定名
A.Bird birdA = new A.Bird();//正确
B.Bird birdB = new B.Bird();//正确
  • 创立类型别名
namespace C
{
    //为A.Bird定义别名为BirdA 
    using BirdA = A.Bird;
    //为B.Bird定义别名为BirdB
    using BirdB = B.Bird;
    class Person
    {
        void Test()
        {
            BirdA birdA = new BirdA(); //相当于A.Bird birdA = new A.Bird()
            BirdB birdB = new BirdB(); //相当于B.Bird birdB = new B.Bird()
        }
    }
}
  • 创立命名空间别名
namespace A.B.C
{
    class Bird
    {
        public string Name { get; set; }
    }
}
namespace D.E.F
{
    class Bird
    {
        public string Name { get; set; }
    }
}
namespace C
{
    //命名空间别名
    using A = A.B.C;
    using D = D.E.F;
    class Person
    {
        void Test()
        {
            A::Bird birdA = new A::Bird() { Name = "一只彩色的鸟" };
            D::Bird birdD = new D::Bird() { Name = "一只红色的鸟" };
        }
    }
}

*最初一点倡议: 尽管能够通过创立类型别名或命名空间别名的形式打消歧义性,但还是倡议定义类型时使类型名称惟一

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理