为什么不能在对象初始化期间使用部分限定的命名空间?

本文关键字:命名空间 用部 不能 对象 初始化 为什么 | 更新日期: 2023-09-27 18:15:54

我怀疑这是一个已经问过很多次的问题,但我还没有找到一个。

我通常使用完全限定的命名空间,如果我不经常在文件中使用这种类型,或者我在文件的顶部添加using namaspacename,以便能够写new ClassName()

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

考虑在嵌套命名空间中使用以下类:

namespace ns_1
{
    namespace ns_1_1
    {
        public class 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'无法找到(您是否缺少using指令或程序集引用?)

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

我没有找到语言规范,在哪里记录的?为什么编译器没有足够的智能来检查是否有一个类命名空间(-part)?


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

using System.Data;
public class Program
{
    public Program()
    {
        using (var con = new SqlClient.SqlConnection("...")) // doesn't work
        {
            //... 
        }
    }
}

编辑:现在我知道为什么这对我来说很奇怪了。它在VB中工作没有问题。净:

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

为什么不能在对象初始化期间使用部分限定的命名空间?

这种明显的方式不幸不起作用,但您可以通过别名命名空间来实现这一切:

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

文档说:

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

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

这在3.8命名空间和类型名称的标准中有记录,但是要遵循它有点复杂。

它的要点是,部分名称空间引用只在它出现的名称空间中查找,并向外每层查找。不检查using -指令

在您的示例中,如果在

中找到Foo,则会找到ns_1_1.Foo:
Program.Program.ns_1_1.Foo
Program.ns_1_1.Foo
ns_1_1.Foo

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

例如,这将工作,因为您当前的名称空间是ns_1

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