关于c#:命名空间

47次阅读

共计 2743 个字符,预计需要花费 7 分钟才能阅读完成。

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

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

成员依据相关性能够将 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 = "一只红色的鸟"};
        }
    }
}

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

正文完
 0