命名空间和使用范围解析

时间:2017-11-15 02:10:49

标签: c# .net-core

我在C#.NET Core 2.0中遇到了一些奇怪的东西,我想知道这里发生了什么。

我有一个名为FooBar.cs的文件,看起来像这个

namespace Foo
{
    public class FooClass
    {

    }

    namespace Bar
    {
        enum BarEnums
        {
             Bar1
            ,Bar2
            ,Bar3
        }
    }
}

我有一个看起来像这样的简单程序

using System;

using Foo;

namespace Using
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");

            FooClass fooClass = new FooClass();

            Console.WriteLine(Bar.BarEnums.Bar1);
        }
    }
}

这给了我以下错误:

Program.cs(16,22): error CS0103: The name 'Bar' does not exist in the current context

我很困惑为什么using语句在名称空间中公开了类,但是它没有公开在同一级别找到的命名空间?如果我输入using Foo.Bar它仍会给出相同的错误..所以using语句可以看到命名空间,但它无法帮助它找到下面的引用。

现在,如果我输入Foo.Bar.BarEnums.Bar1它会正常工作..但为什么我不必按照与引用枚举相同的命名法放入Foo.FooClass?这只是在命名空间中访问枚举与类之间的区别吗?

1 个答案:

答案 0 :(得分:3)

这是因为using Foo仅导入给定命名空间中包含的类型,但它并不专门导入嵌套的命名空间。这就是为什么当您引用enum时必须使用完整的命名空间引用。

这是C#语言规范。

以下是来自C#团队成员的解释:

  

在C#中,指定“using”子句时,例如

     

使用System.Text;

     

编译器只将System.Text中的类型导入全局   命名空间 - 它对内部的任何命名空间都不做同样的事情   System.Text。所以,虽然这种使用允许我写:

     

StringBuilder s = new StringBuilder();

     

它不允许我写:

     

RegularExpressions.Regex r = new RegularExpressions.Regex();

     

为什么?

     

嗯,早期版本的C#编译器有这种行为,但我们   发现它有一些问题:

     

首先,它使代码更难以遵循。在上面的例子中,   RegularExpressions.Regex()可以是全局名称,也可以是基于的名称   我的任何使用条款。必须查看代码的顶部   找出一个名字是我们想要避免的东西。

     

第二个问题与命名空间名称之间的冲突有关,   这种行为更经常发生。如果有的话   其中包含RegularExpressions命名空间的另一个命名空间,   用户将无法为两者都使用“使用”语句 - 甚至   如果他们实际上并不关心那个命名空间。

     

因此,我们决定改变行为。

https://blogs.msdn.microsoft.com/csharpfaq/2004/03/07/why-dont-namespace-using-directives-import-nested-namespaces/

这是C#规范:https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/namespaces