System.Collections是"System命名空间的命名空间"吗?

25

好的,我一直在阅读一本关于C#和.NET的书,当学习DateTime结构和以下代码时:

DateTime dt = new DateTime(2015, 10, 17);

我问自己:“为什么我不需要在顶部写上using System.DateTime来引用它呢?”

后来我意识到,由于DateTime是一个结构体,而“using”关键字是用来引用类型(类型是一个通用术语,用于指代来自集合{类、接口、结构体、枚举、委托}的成员),这些类型定义在特定的命名空间中(在本例中,DateTime是System命名空间中的结构体类型)。

但我注意到,在文件顶部,以下using指令被找到(当我创建C#控制台应用程序时,它们是自动放在那里的):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

当我们已经在 System 命名空间下时,为什么需要使用在 using System 后面声明的 using 指示呢?难道它们不都属于 System 命名空间吗,因此应该已经被引用了吗?

我猜想是因为它们下面声明的都是命名空间,而不是 {class, interface, structure, enumeration, delegate} 集合中的类型。但是如果我们将它们称为“属于命名空间 System 的命名空间”,这样说是否不正确?如果不正确,为什么必须显式地引用命名空间的命名空间,而不能将它们隐式地包含在using System之下呢?

希望我的问题表达清晰,如果有不清楚的地方,请告诉我以便我进行编辑。


1
只是为了澄清你似乎有的误解:在你的示例中,使用后面跟着的都是命名空间。你永远不会像这样使用 using System.DateTime,因为你从来没有类(或结构体)使用这种语法。有其他使用 using 的方法,这些方法在 https://msdn.microsoft.com/en-us/library/sf0df423.aspx 中有描述。就名称解析而言,结构体和类(以及接口和任何其他你能想到的东西)都可以工作得一样好。 - Chris
4个回答

24

在内部,所有的 .net 类型都具有完整的类型名称。

System.DateTime
System.Collections.Generic.Dictionary<string, int>
System.Threading.Tasks.Task

'usings' 的作用是让你在引用 '.' 字符之前的所有内容时更加隐蔽。所以当你写下

DateTime

C#将会尝试

System.DateTime
System.Collections.Generic.DateTime
System.Linq.DateTime
System.Text.DateTime
etc...

由于只存在一个(System.DateTime),它是一个明确的匹配,C#知道你在谈什么。

如果有两个匹配项,编译器会报告歧义的错误。因此,如果存在一个System.Threading.Task.DateTime,你的程序将无法编译。

所有这些都为回答你的问题铺平了道路。 如果

using System;

如果将其下方的所有内容都包括在内,那么很难确保事物不会产生歧义。例如,如果您想区分两个理论类别

System.WebPages.Button
System.Desktop.Button

在这种情况下,一个简单的 using System 将无法与 new Button() 很好地配合使用。


3
原因是如果不这样做,在某些情况下,您将无法避免不想要的名称冲突。例如,如果您在Foo命名空间中有一个类型为Baz,并且在Foo.Bar命名空间中也有一个类型为Baz,则您始终必须在代码中完全限定您的类型,例如Foo.BazFoo.Bar.Baz,这将使using指令没有意义。
现在它是这样的,只有当您实际上在包含您的类型的两个命名空间中都有using指令时,您才必须处理名称冲突。

2

你不需要其他的using指令,例如如果你想要一个List,你可以在你的代码中直接声明:

System.Collections.Generic.List<String> listOfStrings = new System.Collections.Generic.List<String>;

为了创建一个新的列表,使用语句让你可以简单地声明它如下:
List<String> listOfStrings = new List<String>;

只用下面的代码,你无法进行后者的操作:

using System;

因为在System中可能会有一个名为List的类,也可能存在于System.Collections.Generic中。如果是这样,当您创建新的列表对象时,它如何知道您正在引用哪个List类?
因此,命名空间主要用于防止名称冲突,并使程序员能够将事物分组到逻辑上命名的组中,例如,与输入和输出相关的类可以在System.IO中找到。

1
创建一个using指令以使用命名空间中的类型而无需指定命名空间。using指令不会让你访问任何嵌套在你指定的命名空间中的命名空间。
来自https://msdn.microsoft.com/en-us/library/sf0df423.aspx 当我因我的文件夹结构被分配命名空间时,例如projectName\Code\DBFiles,如果我在其中一个控制器上使用Code;,它不会让我访问DBFiles中的类,这就是为什么我将所有类名空间设置为根命名空间的原因。

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