首页 > C# > 在 C# 中,“using”指令应该在命名空间内部还是外部?

在 C# 中,“using”指令应该在命名空间内部还是外部?

上一篇 下一篇

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

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

分割线

网友回答:

两者之间实际上有一个(微妙的)区别。假设您在 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
    {
    }
}

编译器在查看命名空间外部的这些指令之前进行搜索,因此它会找到而不是 .不幸的是(或者也许是幸运的?),没有成员,所以File1现在被破坏了。OuterusingOuter.MathSystem.MathOuter.MathPI

如果将命名空间声明放入命名空间声明中,则会更改,如下所示:using

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

现在编译器先搜索再搜索,找到,一切都很好。SystemOuterSystem.Math

有些人会争辩说,对于用户定义的类来说,这可能是一个不好的名字,因为 ;这里的重点只是存在差异,它会影响代码的可维护性。MathSystem

注意如果在命名空间中而不是 .在这种情况下,添加 File2 会中断 File1,无论它去哪里。这意味着编译器在查看任何指令之前会搜索最里面的封闭命名空间。FooOuterOuter.InnerOuter.Mathusingusing

分割线

网友回答:

这个线程已经有一些很好的答案,但我觉得我可以通过这个额外的答案带来更多细节。

首先,请记住带有句点的命名空间声明,例如:

namespace MyCorp.TheProduct.SomeModule.Utilities
{
    ...
}

完全等同于:

namespace MyCorp
{
    namespace TheProduct
    {
        namespace SomeModule
        {
            namespace Utilities
            {
                ...
            }
        }
    }
}

如果你愿意,你可以在所有这些级别上放置指令。(当然,我们只希望在一个地方使用s,但根据语言,这是合法的。usingusing

解析隐含类型的规则可以这样粗略地表述:首先在最里面的“范围”中搜索匹配项,如果未找到任何内容,则从一级到下一个范围并在那里搜索,依此类推,直到找到匹配项。如果在某个级别找到多个匹配项,如果其中一个类型来自当前程序集,请选择该类型并发出编译器警告。否则,放弃(编译时错误)。

现在,让我们在两个主要约定的具体示例中明确这意味着什么。

(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

  1. 内部嵌套类型(包括继承的嵌套类型)C
  2. 当前命名空间中的类型MyCorp.TheProduct.SomeModule.Utilities
  3. 命名空间中的类型MyCorp.TheProduct.SomeModule
  4. 类型在MyCorp.TheProduct
  5. 类型在MyCorp
  6. 命名空间(全局命名空间)中的类型
  7. 在 、 、 、 和 中键入SystemSystem.Collections.GenericSystem.LinqMyCorp.TheProduct.OtherModuleMyCorp.TheProduct.OtherModule.IntegrationThirdParty

另一个约定:

(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

  1. 内部嵌套类型(包括继承的嵌套类型)C
  2. 当前命名空间中的类型MyCorp.TheProduct.SomeModule.Utilities
  3. 在 、 、 和 中键入SystemSystem.Collections.GenericSystem.LinqMyCorp.TheProductMyCorp.TheProduct.OtherModuleMyCorp.TheProduct.OtherModule.IntegrationThirdParty
  4. 命名空间中的类型MyCorp.TheProduct.SomeModule
  5. 类型在MyCorp
  6. 命名空间(全局命名空间)中的类型

(请注意,这是“3.”的一部分,因此在“4.”和“5”之间不需要。MyCorp.TheProduct

结束语

无论您将 uses 放在命名空间声明的内部还是外部,总有可能有人稍后将具有相同名称的新类型添加到具有更高优先级的命名空间之一。

此外,如果嵌套命名空间与类型同名,则可能会导致问题。

将用途从一个位置移动到另一个位置总是危险的,因为搜索层次结构会发生变化,并且可能会找到另一种类型。因此,选择一个约定并坚持下去,这样你就不必移动使用。

默认情况下,Visual Studio 的模板将 using 放在命名空间之外(例如,如果让 VS 在新文件中生成一个新类)。

在外部使用 using 的一个(微小)优点是,您可以将 using 指令用于全局属性,例如代替 .[assembly: ComVisible(false)][assembly: System.Runtime.InteropServices.ComVisible(false)]


有关文件范围的命名空间声明的更新

从 C# 10.0(从 2021 年开始)开始,可以避免缩进并使用其中之一(约定 1,在外部使用):

using System;
using System.Collections.Generic;
using System.Linq;
using MyCorp.TheProduct.OtherModule;
using MyCorp.TheProduct.OtherModule.Integration;
using ThirdParty;

namespace MyCorp.TheProduct.SomeModule.Utilities;

class C
{
    Ambiguous a;
}

或(约定 2,内部使用):

namespace MyCorp.TheProduct.SomeModule.Utilities;

using System;
using System.Collections.Generic;
using System.Linq;
using MyCorp.TheProduct;
using MyCorp.TheProduct.OtherModule;
using MyCorp.TheProduct.OtherModule.Integration;
using ThirdParty;

class C
{
    Ambiguous a;
}

但与以前相同的考虑因素适用。

分割线

网友回答:

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

using ThisNamespace.IsImported.InAllNamespaces.Here;

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

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

namespace Namespace3
{ 
   using ThisNamespace.IsImported.InJustNamespace3;
}

模板简介:该模板名称为【在 C# 中,“using”指令应该在命名空间内部还是外部?】,大小是暂无信息,文档格式为.编程语言,推荐使用Sublime/Dreamweaver/HBuilder打开,作品中的图片,文字等数据均可修改,图片请在作品中选中图片替换即可,文字修改直接点击文字修改即可,您也可以新增或修改作品中的内容,该模板来自用户分享,如有侵权行为请联系网站客服处理。欢迎来懒人模板【C#】栏目查找您需要的精美模板。

相关搜索
  • 下载密码 lanrenmb
  • 下载次数 327次
  • 使用软件 Sublime/Dreamweaver/HBuilder
  • 文件格式 编程语言
  • 文件大小 暂无信息
  • 上传时间 04-24
  • 作者 网友投稿
  • 肖像权 人物画像及字体仅供参考
栏目分类 更多 >
热门推荐 更多 >
响应式 自适应 微信素材 微信图片 企业网站 微信公众平台 微信模板 单页式简历模板 微信文章 html5
您可能会喜欢的其他模板