这个线程已经有了一些不错的答案,但是我觉得我可以通过这个额外的答案来详细介绍一下。
首先,请记住带有句点的名称空间声明,例如:
namespace MyCorp.TheProduct.SomeModule.Utilities
{
...
}
完全等同于:
namespace MyCorp
{
namespace TheProduct
{
namespace SomeModule
{
namespace Utilities
{
...
}
}
}
}
如果愿意,可以将using
指令放在所有这些级别上。(当然,我们只想using
在一个位置使用,但是根据语言,这是合法的。)
解决隐含类型的规则可以大致这样表示:首先在最内层的“范围”中查找匹配项,如果没有找到匹配项,则进入下一个范围并在那里搜索,依此类推,直到找到匹配项。如果在某种程度上找到多个匹配项,并且其中一种类型来自当前程序集,则选择该一种并发出编译器警告。否则,放弃(编译时错误)。
现在,让我们在两个主要约定的具体示例中明确说明其含义。
(1)外部使用:
using System;
using System.Collections.Generic;
using System.Linq;
//using MyCorp.TheProduct; <-- uncommenting this would change nothing
using MyCorp.TheProduct.OtherModule;
using MyCorp.TheProduct.OtherModule.Integration;
using ThirdParty;
namespace MyCorp.TheProduct.SomeModule.Utilities
{
class C
{
Ambiguous a;
}
}
在上述情况下,要找出类型Ambiguous
是什么,搜索按以下顺序进行:
- 内部的嵌套类型
C
(包括继承的嵌套类型)
- 在当前名称空间中输入
MyCorp.TheProduct.SomeModule.Utilities
- 命名空间中的类型
MyCorp.TheProduct.SomeModule
- 输入
MyCorp.TheProduct
- 输入
MyCorp
- 输入空名称空间(全局名称空间)
- 类型
System
,System.Collections.Generic
,System.Linq
,MyCorp.TheProduct.OtherModule
,MyCorp.TheProduct.OtherModule.Integration
,和ThirdParty
另一个约定:
(2)内部使用:
namespace MyCorp.TheProduct.SomeModule.Utilities
{
using System;
using System.Collections.Generic;
using System.Linq;
using MyCorp.TheProduct; // MyCorp can be left out; this using is NOT redundant
using MyCorp.TheProduct.OtherModule; // MyCorp.TheProduct can be left out
using MyCorp.TheProduct.OtherModule.Integration; // MyCorp.TheProduct can be left out
using ThirdParty;
class C
{
Ambiguous a;
}
}
现在,搜索类型Ambiguous
按以下顺序进行:
- 内部的嵌套类型
C
(包括继承的嵌套类型)
- 在当前名称空间中输入
MyCorp.TheProduct.SomeModule.Utilities
- 类型
System
,System.Collections.Generic
,System.Linq
,MyCorp.TheProduct
,MyCorp.TheProduct.OtherModule
,MyCorp.TheProduct.OtherModule.Integration
,和ThirdParty
- 命名空间中的类型
MyCorp.TheProduct.SomeModule
- 输入
MyCorp
- 输入空名称空间(全局名称空间)
(请注意,这MyCorp.TheProduct
是“ 3.”的一部分,因此在“ 4.”和“ 5.”之间不需要。)
结束语
无论将usings放在名称空间声明的内部还是外部,总有可能有人后来向具有更高优先级的名称空间之一添加了具有相同名称的新类型。
另外,如果嵌套名称空间的名称与类型的名称相同,则可能导致问题。
将使用从一个位置移动到另一个位置始终很危险,因为搜索层次结构会发生变化,并且可能会找到另一种类型。因此,选择一种约定并坚持下去,这样您就不必再搬家了。
默认情况下,Visual Studio的模板将使用情况放在命名空间之外(例如,如果让VS在新文件中生成新类)。
在外部使用的一个(微小)优点是您可以将using指令用于全局属性,例如[assembly: ComVisible(false)]
代替[assembly: System.Runtime.InteropServices.ComVisible(false)]
。