我一直在一些C#代码上运行StyleCop,它不断报告我的using指令应该在命名空间中。

是否有技术原因将using指令放在命名空间内部而不是外部?


当前回答

尚未提及:

将using指令放在命名空间声明中是众所周知的最佳编程实践的一个应用,即在尽可能小的范围内声明所有内容。

如果最佳编程实践是您的第二天性,那么您可以自动执行类似的操作。

这可能是将using指令放在命名空间声明中的最佳理由,而不管其他地方提到的(边界)技术(边界)优点;就这么简单。


已经提到了,但可能更好地说明了:

在名称空间中放置using指令可以避免不必要的重复,并使声明更加简洁。

这是不必要的简洁:

using Com.Acme.Products.Traps.RoadRunnerTraps;
namespace Com.Acme.Products.Traps {

这是甜蜜的,切中要害:

namespace Com.Acme.Products.Traps { 
using RoadRunnerTraps;

其他回答

尚未提及:

将using指令放在命名空间声明中是众所周知的最佳编程实践的一个应用,即在尽可能小的范围内声明所有内容。

如果最佳编程实践是您的第二天性,那么您可以自动执行类似的操作。

这可能是将using指令放在命名空间声明中的最佳理由,而不管其他地方提到的(边界)技术(边界)优点;就这么简单。


已经提到了,但可能更好地说明了:

在名称空间中放置using指令可以避免不必要的重复,并使声明更加简洁。

这是不必要的简洁:

using Com.Acme.Products.Traps.RoadRunnerTraps;
namespace Com.Acme.Products.Traps {

这是甜蜜的,切中要害:

namespace Com.Acme.Products.Traps { 
using RoadRunnerTraps;

事实上,两者之间有(微妙的)区别。假设您在File1.cs中有以下代码:

// File1.cs
using System;
namespace Outer.Inner
{
    class Foo
    {
        static void Bar()
        {
            double d = Math.PI;
        }
    }
}

现在想象一下,有人将另一个文件(File2.cs)添加到项目中,如下所示:

// File2.cs
namespace Outer
{
    class Math
    {
    }
}

编译器在查看命名空间外使用指令的对象之前搜索Outer,因此找到Outer.Math而不是System.Math。不幸的是(或者幸运的是?),Outer.Math没有PI成员,因此File1现在已损坏。

如果将using放在命名空间声明中,则会发生如下变化:

// File1b.cs
namespace Outer.Inner
{
    using System;
    class Foo
    {
        static void Bar()
        {
            double d = Math.PI;
        }
    }
}

现在编译器先搜索System,再搜索Outer,找到System.Math,一切正常。

有些人会认为Math对于用户定义的类来说可能是个坏名字,因为System中已经有一个;这里的重点是存在差异,这会影响代码的可维护性。

如果Foo位于命名空间Outer,而不是Outer.Inner,会发生什么也很有趣。在这种情况下,在File2中添加Outer.Math会破坏File1,而不管使用的位置如何。这意味着编译器在查看任何using指令之前搜索最内部的封闭命名空间。

如果源解决方案中使用的默认引用(即“引用”)应该在命名空间之外,而那些“新添加的引用”是一个很好的做法,则应将其放在命名空间内。这是为了区分要添加的引用。

通常,外部using指令(例如System和Microsoft命名空间)应该放在命名空间指令之外。除非另有规定,否则应在所有情况下应用默认值。这应该包括不属于当前项目的任何组织内部库,或者使用引用同一项目中其他主名称空间的指令。引用当前项目和命名空间中其他模块的任何using指令都应放在命名空间指令中。这有两个特定的功能:

它提供了本地模块和“其他”模块之间的视觉区别,这意味着所有其他模块。它将本地指令的范围限定为优先于全局指令应用。

后一个原因很重要。这意味着很难引入一个不明确的引用问题,而这个引用问题可能是由一个比重构代码更重要的更改引起的。也就是说,你将一个方法从一个文件移动到另一个文件,突然出现了一个以前不存在的bug。通俗地说,一个“海森堡”——历史上极难追踪。

将其放在名称空间中会使声明成为文件的该名称空间的本地声明(如果文件中有多个名称空间),但如果每个文件只有一个名称空间,那么它们在名称空间外部还是内部都没有太大区别。

using ThisNamespace.IsImported.InAllNamespaces.Here;

namespace Namespace1
{ 
   using ThisNamespace.IsImported.InNamespace1.AndNamespace2;

   namespace Namespace2
   { 
      using ThisNamespace.IsImported.InJustNamespace2;
   }       
}

namespace Namespace3
{ 
   using ThisNamespace.IsImported.InJustNamespace3;
}