C# 为什么可以';在对象初始化期间我是否使用部分限定的名称空间?

C# 为什么可以';在对象初始化期间我是否使用部分限定的名称空间?,c#,types,compiler-construction,compiler-errors,namespaces,C#,Types,Compiler Construction,Compiler Errors,Namespaces,我怀疑这是一个以前被问过很多次的问题,但我还没有找到一个 如果我不经常在文件中使用完全限定的名称空间,或者我在文件顶部添加了使用namaspacename,以便能够写入新的ClassName(),那么我通常使用完全限定的名称空间 但是,如果只添加了完整名称空间的一部分,该怎么办?为什么编译器找不到类型并抛出错误 考虑嵌套命名空间中的以下类: namespace ns_1 { namespace ns_1_1 { public class Foo { } }

我怀疑这是一个以前被问过很多次的问题,但我还没有找到一个

如果我不经常在文件中使用完全限定的名称空间,或者我在文件顶部添加了
使用namaspacename
,以便能够写入
新的ClassName()
,那么我通常使用完全限定的名称空间

但是,如果只添加了完整名称空间的一部分,该怎么办?为什么编译器找不到类型并抛出错误

考虑嵌套命名空间中的以下类:

namespace ns_1
{
    namespace ns_1_1
    {
        public class Foo { }
    }
}
using ns_1_1 = ns_1.ns_1_1;

public class Program
{
    public Program()
    {
        var no_foo = new ns_1_1.Foo();
    }
}
因此,如果我现在想初始化这个类的实例,它的工作方式如下:

using ns_1.ns_1_1;

public class Program
{
    public Program()
    {
        // works, fully qualified namespace:
        var foo = new ns_1.ns_1_1.Foo();
        // works, because of using ns_1.ns_1_1:
        foo = new Foo();
    }
}
但以下方法不起作用:

using ns_1;

public class Program
{
    public Program()
    {
        // doesn't work even if using ns_1 was added
        var no_foo = new ns_1_1.Foo();
    }
}
它抛出编译器错误:

找不到类型或命名空间名称“ns_1_1”(是否为空) 缺少使用指令或程序集引用?)

我假设,因为
ns_1_1
被视为一个类,它包含另一个类
Foo
,而不是名称空间,这是正确的吗

我还没有找到语言规范,在哪里有文档记录?为什么编译器不够聪明,无法检查是否存在类命名空间(-part)


下面是我的另一个不那么抽象的例子:

using System.Data;

public class Program
{
    public Program()
    {
        using (var con = new SqlClient.SqlConnection("...")) // doesn't work
        {
            //... 
        }
    }
}
编辑:现在我知道为什么这对我来说很奇怪了。它在VB.NET中正常工作:

Imports System.Data

Public Class Program
    Public Sub New()
        Using con = New SqlClient.SqlConnection("...") ' no problem

        End Using
    End Sub
End Class

这在中的标准中有记录,但遵循起来有点复杂

其要点是,只在部分名称空间引用出现的名称空间中查找它,并向外查找每个层<代码>使用-未选中指令

在您的示例中,如果在以下位置找到
Foo
,则会找到
ns_1_1.Foo

Program.Program.ns_1_1.Foo
Program.ns_1_1.Foo
ns_1_1.Foo
报告说:

创建一个using指令来使用命名空间中的类型,而不必指定命名空间using指令不允许您访问嵌套在指定名称空间中的任何名称空间。


因此,
using
只包括在指定名称空间中定义的类型(而不是名称空间)。为了访问嵌套名称空间的类型,您需要像在第一个示例中那样使用
指令显式指定它。

只有当当前类是该部分名称空间的一部分时,部分名称空间才会工作。通过部分命名空间访问类型时不考虑使用语句

例如,这将起作用,因为您当前的名称空间是
ns\u 1

namespace ns_1
{
    public class Program
    {
        public Program()
        {
            var no_foo = new ns_1_1.Foo();
        }
    }
}

不幸的是,这种显而易见的方法不起作用,但您可以通过别名命名空间实现这一切:

namespace ns_1
{
    namespace ns_1_1
    {
        public class Foo { }
    }
}
using ns_1_1 = ns_1.ns_1_1;

public class Program
{
    public Program()
    {
        var no_foo = new ns_1_1.Foo();
    }
}

谢谢这似乎回答了我的问题。但是,为什么C#编译器不够聪明(或者不希望)使用
将外部名称空间的名称空间包含在
中?(可能这是E.Lippert的问题)VB.NET支持我的答案中所示的问题。为了避免歧义,可能。。例如,如果您有另一个未嵌套的
SqlClient
命名空间,并且包含另一个
SqlConnection
类,会发生什么情况?你在VB中试过这个吗?如何避免歧义?是否要求您指定完全限定名?然后VB在另一个
SqlClient
命名空间中使用新类。它似乎赢了,因为它是完全合格的,而ambigous类型只是部分合格。谢谢。现在还不清楚为什么我不能在C#中使用它,而不是VB.NET。但我想我知道Erip Lippert会给出的答案:因为该功能的估计收益不值得它的实现成本。这听起来有点像他,我同意:)有趣的是,如果你把它改为“namespace ns_1.ns_2_2”,新的ns_1_1.Foo()仍然有效。它似乎首先在当前名称空间中查找,然后在当前名称空间的父级中查找,依此类推。