简体   繁体   English

这两个声明有什么区别?

[英]What is the difference between these two declarations?

Given this declaration: 鉴于此声明:

using System;
using System.Collections;
using System.Collections.Generic;

namespace AProject.Helpers
{
    public static class AClass
    {

and this declaration 和这个宣言

namespace AProject.Helpers
{
    using System;
    using System.Collections;
    using System.Collections.Generic;

    public static class AClass
    {

are there any difference in any sense between them? 他们之间有什么区别吗? Or is just a difference in coding styles? 或者只是编码风格的差异?

I allways used to declared my classes like the first, but recently noticed that Microsoft uses the second . 我总是习惯于像第一个一样宣布我的课程,但最近注意到微软使用了第二个

In the latter version the using directives only apply within the namespace declaration. 在后一版本中,using指令仅适用于名称空间声明。

In most cases you'll only have a single namespace declaration: 在大多数情况下,您只有一个名称空间声明:

// Using directives
...
namespace X
{
    // Maybe more using directives
    // Code
}
// End of file

The main difference is if you have multiple namespaces in the same file: 主要区别在于,如果同一文件中有多个名称空间:

// Using directives
...
namespace X
{
    // Maybe more using directives
    // Code
}

namespace Y
{
    // Maybe more using directives
    // Code
}
// End of file

In this case the using directives in the namespace X declaration don't affect the code inside the namespace Y declaration, and vice versa. 在这种情况下,名称空间X声明中的using指令不会影响名称空间Y声明中的代码,反之亦然。

However, that's not the only difference - there's a subtle case which Eric Lippert points out where it can affect the code even with just a single namespace declaration. 然而,这并不是唯一的区别 - 有一个微妙的案例,Eric Lippert指出它可以影响代码,即使只有一个命名空间声明。 (Basically if you write using Foo; inside the namespace X declaration, and there's a namespace X.Foo as well as Foo , the behaviour changes. This can be remedied using a namespace alias, eg using global::Foo; if you really want.) (基本上如果你using Foo;编写using Foo;在命名空间X声明中,并且有一个命名空间X.Foo以及Foo ,行为会发生变化。这可以使用命名空间别名来解决,例如using global::Foo;如果你真的想要。)

Personally I'd stick to: 我个人坚持:

  • One namespace declaration per file (and usually one top-level type per file) 每个文件一个名称空间声明(通常每个文件一个顶级类型)
  • Using directives outside the namespace declaration 使用名称空间声明之外的指令

It makes the using directives local to that namespace, which in practice should make no difference since you're (hopefully) not declaring multiple types in multiple namespaces in a single source file. 它使得该命名空间的using指令本地化,实际上应该没有区别,因为你(希望)没有在单个源文件中声明多个命名空间中的多个类型。

Details here . 细节在这里

The second can be ambiguous; 第二个可能含糊不清;

The top one makes it clear your after these namespaces: 最重要的一个是在这些命名空间之后清楚地表明你:

  • System 系统
  • System.Collections System.Collections中
  • System.Collections.Generic System.Collections.Generic

While the second one will first look for these namespaces: 而第二个将首先查找这些名称空间:

  • AProject.Helpers.System AProject.Helpers.System
  • AProject.Helpers.System.Collections AProject.Helpers.System.Collections
  • AProject.Helpers.System.Collections.Generic AProject.Helpers.System.Collections.Generic

And refer to them instead if they're found... If not, they'll both refer to the same namespaces. 如果找到它们,请参考它们......如果没有,它们都将引用相同的命名空间。

The safer rewrite of the second one would be: 第二个更安全的重写将是:

namespace AProject.Helpers
{
    using global::System;
    using global::System.Collections;
    using global::System.Collections.Generic;
}

Another important difference between them arises when using LINQ-to-SQL and the generated datacontext classes. 当使用LINQ-to-SQL和生成的datacontext类时,会出现它们之间的另一个重要区别。 For example, the Northwind sample database; 例如,Northwind示例数据库; initially, you get: 最初,你得到:

  • Northwind.dbml
    • Northwind.dbml.layout
    • Northwind.designer.cs

If you now want to extend the partial classes by adding your own Northwind.cs , you get 如果您现在想要通过添加自己的Northwind.cs来扩展分部类,那么您将获得

  • Northwind.dbml
    • Northwind.dbml.layout
    • Northwind.designer.cs
    • Northwind.cs

Amusingly , there is a bug in the code-generator ( MSLinqToSQLGenerator ) - which means that if the using directives are outside the namespace (like they are by default), it breaks - with the message: 有趣的是,代码生成器( MSLinqToSQLGenerator )中存在一个错误 - 这意味着如果using指令在命名空间之外 (就像默认情况下那样),它会中断 - 消息:

The custom tool 'MSLinqToSQLGenerator' failed. Unspecified error

And the Northwind.designer.cs file gets deleted. 并且Northwind.designer.cs文件被删除。 No more data-context! 没有更多的数据背景!

However, if you move the using directives inside the namespace (and re-run the custom tool - right click in solution explorer), it works correctly. 但是,如果在命名空间移动using指令(并重新运行自定义工具 - 右键单击​​解决方案资源管理器中),则它可以正常工作。

So: this isn't a language detail - it is simply a bug in the code generator; 所以:这不是语言细节 - 它只是代码生成器中的一个错误; but there is a pretty big difference between "works correctly" and the generated code getting deleted... 但是“正常工作”和生成的代码被删除之间有一个很大的区别......

Note you can also fix this simply by calling your file something different - such as NorthwindExtras.cs . 请注意,您也可以通过调用不同的文件来解决这个问题 - 例如NorthwindExtras.cs

Freaky. 辣妈。

我想可能有理由从纯粹主义的角度使用第二种替代方案,因为它更清楚地表明了using指令的范围是什么。

In the first example, the using declarations are "global" to the whole file. 在第一个示例中,using声明对整个文件是“全局的”。 In the second example, the using statements will only apply to the code wrapped up in the namespace block. 在第二个示例中,using语句仅适用于命名空间块中包含的代码。

I think the only time this really matters is if you have more than one namespace in the file, and want to limit which namespace has access to each using declaration. 我认为唯一真正重要的是,如果文件中有多个命名空间,并希望使用声明限制哪个命名空间可以访问每个命名空间。

And for the process that Arjan points out, it's considered to be bad practice to declare usings inside your namespace. 对于Arjan指出的过程,在命名空间内声明使用是不好的做法。 They can be implicitly overridden by another namespace. 它们可以被另一个名称空间隐式覆盖。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM