为什么使用命名空间以不直观的方式工作?

时间:2017-02-16 01:35:16

标签: c# generics namespaces

我在引用的项目Project.Base中有一个命名空间,有人认为在该命名空间中声明自己的通用List类是个好主意。

现在我有一个开始的代码文件:

using System.Collections.Generic;
using Project.Base.Sub;

Project.Base命名空间从未真正正式使用过;只是一个嵌套的命名空间。 System.Collections.Generic 正式使用。但由于一些奇怪的原因,当我声明一个返回类型为List<T>的方法时,它会将其解释为Project.Base.List<T>而不是System.Collections.Generic.List<T>

这对我来说似乎非常违反直觉。有谁知道发生了什么以及如何解决它?

编辑要重现:

using System;
using System.Collections.Generic;
using Project.Base.Sub;

namespace Project.Base
{
    public class List<T> { }
}

namespace Project.Base.Sub { }

namespace Project.Base.Sub2
{

    public class P
    {
        public static void Main()
        {
            var list = new List<int>(); 
            Console.WriteLine(list.GetType().Namespace);
            Console.Read();
        }
    }
}

(请注意,有问题的代码位于Project.Base的不同子命名空间中。这似乎很重要。)

2 个答案:

答案 0 :(得分:2)

通过搜索封闭的命名空间继续进行名称查找,并且只考虑每个命名空间范围内的using指令。

要进行此编译,您可以将using指令移到其中:

using System;

namespace Project.Base
{
    public class List<T> { }
}

namespace Project.Base.Sub { }

namespace Project.Base.Sub2
{
    using System.Collections.Generic;

    public class P
    {
        public static void Main()
        {
            var list = new List<int>();
            Console.WriteLine(list.GetType().Namespace);
            Console.Read();
        }
    }
}

顶级using指令仅在全局命名空间内,因此只有在封闭命名空间中的查找失败时才会搜索。因此,第一次查找无法找到Project.Base.Sub2.List,但在下一级别找到Project.Base.List。如果失败了,它会尝试找到Project.List类型。

另一个using指令是红鲱鱼。

答案 1 :(得分:2)

接受的答案是正确的。理解该问题的另一种方法是您发布的代码完全等同于

using System;
using System.Collections.Generic;
using Project.Base.Sub;

namespace Project
{
  namespace Base
  {
    public class List<T> { }
    namespace Sub { }
    namespace Sub2 
    { 
      public class P
      {
        public static void Main()
        {
          var list = new List<int>(); 
          Console.WriteLine(list.GetType().Namespace);
          Console.Read();
        }
      }
    }
  }
}

现在应该清楚为什么List会像它一样解决。 List的声明直接在一个封闭的命名空间中。

从设计的角度来看,最好还是让你的同事回过头来,这个同事认为命名一个班级&#34; List&#34;是个好主意。通常声明存在名称空间以防止名称冲突,但这实际上是它们的次要目的。在现实的代码中,通常没有太多的命名冲突,因为人们通常不会做一些令人困惑的事情,例如命名他们自己的类&#34; List&#34;。

命名空间的主要目的是代码组织成逻辑组,以便您可以使用using来进入范围&#34;您可能在程序中使用的内容的名称。这使IntelliSense可以更好地确定您在键入内容时的含义,使代码更易于阅读,等等。如果您发现自己使用命名空间来防止命名冲突,则可能需要考虑是否可以通过某些战术重命名来消除这些冲突。