关于 C# 命名空间结构的困惑

6

我对C#中的命名空间结构有点困惑。我是C#和WPF的新手。

当我创建一个新的WPF项目时,默认情况下会在顶部包含这些命名空间:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

我对这些结构的理解感到困惑。 我明白

using System;

指代System命名空间

但其他像什么呢?

using System.Text;

这是什么意思?

  • 我正在访问名为“System.Text”的单个命名空间吗?
  • 还是我正在访问位于“System”命名空间内部的“Text”命名空间?

此外,如果“Text”嵌套在“System”中,为什么只有“using System”包括所有命名空间?我们需要明确地包含我们使用的每个命名空间吗?


VS有一个菜单项可以清理列表(删除未使用的using)。 - H H
注意:您还可以使用using alias directive。如果由于冲突无法包含命名空间,则using别名指令可能是一个很好的替代品。 - Brian
5个回答

17

使用System.Text;是指我正在使用名为"System.Text"的单个命名空间还是我正在使用嵌套在"System"命名空间内的"Text"命名空间?

是后者。你正在使用嵌套在"System"命名空间内的"Text"命名空间。

请注意,当您说

namespace Foo.Bar.Blah
{
    class C 
    {
    ...

这只是一种简写的方式

namespace Foo
{
    namespace Bar 
    {
        namespace Blah
        {
            class C 
            {
            ...

命名空间只有“简单”的名称。

  

我们是否应该为我们使用的每个命名空间都有一个明确的“using”指令?

通常情况下是这样的。但也有一些情况不需要这么做,例如,如果您有两个包含相同名称类型的命名空间,并且您希望使用两个命名空间中的类型,则在这种情况下使用两个命名空间的“using”可能会过于混乱。此外,“using”会引入扩展方法;如果有一些您不想绑定的扩展方法,请勿包含包含它们的命名空间。

  

如果“Text”嵌套在“System”中,为什么只有“using System”包含所有命名空间?

我不理解问题的措辞方式。我认为您可能是在问:

  

为什么 using System; 无法使简单名称 Text 解析为嵌套命名空间?

也就是说,为什么下面这段代码无法工作:

namespace Foo
{
    namespace Bar
    {
         class Blah {}
    }
}
在另一个文件中:
using Foo;
class Abc : Bar.Blah {}
< p > using Foo; 只包含直接在 Foo 中声明的类型。它不会引入直接在 Foo 中声明的命名空间。C# 的设计者认为这样将命名空间 "引入范围" 太令人困惑了;通常人们使用 using 指令来将类型 "引入范围"。


System.Text是嵌套在System命名空间中的Text,还是简单名称为System.Text之间真的有区别吗? 就我而言,您(a)使用名称Foo.Bar.Blah定义类,(b)不允许在同一项目中使用名称为FooFoo.Bar的任何类,以及(c)使用助手using Foo.Bar作为using alias Blah = Foo.Bar.Blah的快捷方式。 - configurator
1
@configurator:确实,这是另一种看待它的方式,事实上,这也是CLR看待它的方式。 "命名空间"不是CLR类型系统中的概念;相反,每个类型实际上都被赋予了其完全限定名称,其中包含点。 - Eric Lippert

7

命名空间在计算机中的意义通常不是层次结构。位于System.Text下面的类型(例如System.Text.StringBuilder并不被认为是在System中 - 因此,如果您想要来自两者的类型,则需要单独列出它们:

using System;
using System.Text;

只有当涉及到你声明某个东西的命名空间时,它们才被编译器视为层次结构——至少在我能想到的情况下是这样。

namespace Foo.Bar.Baz
{
    class Test
    {
    }
}

Test中,就好像你已经导入了FooFoo.BarFoo.Bar.Baz

当然,命名空间从人类的角度来看确实形成了层次结构,这使得查找事物变得容易。但是编译器和运行时通常不使用那种层次结构的视图。


1
我们是否需要显式地包含我们使用的每个命名空间?
是的,或者完全限定类型名称。
这里有两个命名空间使用。
using System;
using System.Text;

它们是完全独立的。它们的名称暗示了一种关系,但在那些可以被视为象征性的命名空间之外,它们是无关的。

当你只有第一个 using 时,你不能使用 System.Text 的成员。
而且你不需要第一个 using 就能使用第二个。

只有当你编写属于嵌套命名空间的代码时,才会看到一些效果。

namesapce A
{
    namespace B
    {
        class Foo { }
    }

    namespace C
    {
        class Bar { private B.Foo f; }  // B is a 'relative' ns
    }
}

好的,谢谢。但是结构呢?它是嵌套的还是单一命名空间? - ammar26
嵌套结构表示“逻辑”关系,但没有真正的语义。 - H H

0

您正在访问嵌套在System命名空间中的Text命名空间。是的,您需要包含您使用的每个命名空间。

命名空间结构可以看起来像以下内容:

namespace Parent
{
    namespace Child
    {
        public class ChildClass
        {
        }
    }
}

类似以下内容 - Frank Allenby
@Henk,好的,我看到了四个,另外两个在哪里呢?:o - Blindy

0

using System.Text 导入了 System.Text 中的所有声明,但不包括其文件夹中的任何内容。与 Java 不同,没有类似于 System.Text.* 的等效语法。

处理命名空间的简单方法是正常编写代码,然后在未定义的关键字上按 CTRL+.,以告诉 VS.NET 自动为您添加 using 引用。


更准确地说,所有的非别名 using 指令都像 Java 中的 import System.Text.*;。没有 Java 的单类型导入的等价物,例如 import java.util.Map; - 你不能写成 using System.Collections.Generic.IEnumerable<T>; - Jon Skeet
我以为.*也会添加所有的子名称空间。已经很久没有使用Java了... - Blindy
不,它并不是 - 它是该包内的所有类型。 - Jon Skeet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接