将C#名称空间编译成IL文件是否为"完整"名称?

vik*_*ata 4 c# il namespaces

例如,如果我有

namespace a
    namespace b
{
    class C...
    class D...
}
Run Code Online (Sandbox Code Playgroud)

那么在编译之后,在IL文件中,命名空间信息在哪里?我是否得到两个名为abC和abD的类,其中类名以名称空间名称作为前缀?

或者我在汇编文件中获得了一个名称空间ab,并在其中包含C/D类,就像C#代码一样?

Ara*_*yan 5

CLR对名称空间一无所知.当您访问类型时,CLR需要知道类型的全名以及哪个程序集包含类型的定义,以便运行时可以加载正确的程序集,查找类型并对其进行操作.

这意味着你class Cnamespace b存储就像存储一样b.C.


xan*_*tos 4

另外两个回复写了一些东西,所以我必须写相反的:-)

假设 Microsoft 在两个阵营中都占有一席之地......阅读ECMA-335

第114页

虽然某些编程语言引入了命名空间的概念,但 CLI 中对此概念的唯一支持是作为元数据编码技术。类型名称始终由相对于定义它们的程序集的全名来指定。

但即使是这个 ECMA 标准也自由地使用了命名空间概念:

为了防止将来发生名称冲突,系统名称空间中的所有自定义属性都保留用于标准化。

而IL语言支持该.namespace指令,相当于C#的命名空间指令(该指令在ECMA标准中命名,但没有示例。ILASM正确编译了该示例,反编译后的代码就是我们所期望的)。 。

.namespace A
{
    .namespace B
    {
        .class public auto ansi beforefieldinit C
            extends [mscorlib]System.Object
        {
            // Nested Types
            .class nested public auto ansi beforefieldinit D
                extends [mscorlib]System.Object
            {
                // Methods
                .method public hidebysig specialname rtspecialname 
                    instance void .ctor () cil managed 
                {
                    // Method begins at RVA 0x2050
                    // Code size 7 (0x7)
                    .maxstack 8

                    IL_0000: ldarg.0
                    IL_0001: call instance void [mscorlib]System.Object::.ctor()
                    IL_0006: ret
                } // end of method D::.ctor

            } // end of class D


            // Methods
            .method public hidebysig specialname rtspecialname 
                instance void .ctor () cil managed 
            {
                // Method begins at RVA 0x2050
                // Code size 7 (0x7)
                .maxstack 8

                IL_0000: ldarg.0
                IL_0001: call instance void [mscorlib]System.Object::.ctor()
                IL_0006: ret
            } // end of method C::.ctor

        } // end of class A.B.C
    }
}
Run Code Online (Sandbox Code Playgroud)

但请注意,生成的代码相当于不使用.namespace并直接在 中包含全名.class

.class public auto ansi beforefieldinit A.B.C
    extends [mscorlib]System.Object
{
    // Nested Types
    .class nested public auto ansi beforefieldinit D
        extends [mscorlib]System.Object
    {
        // Methods
        .method public hidebysig specialname rtspecialname 
            instance void .ctor () cil managed 
        {
            // Method begins at RVA 0x2050
            // Code size 7 (0x7)
            .maxstack 8

            IL_0000: ldarg.0
            IL_0001: call instance void [mscorlib]System.Object::.ctor()
            IL_0006: ret
        } // end of method D::.ctor

    } // end of class D


    // Methods
    .method public hidebysig specialname rtspecialname 
        instance void .ctor () cil managed 
    {
        // Method begins at RVA 0x2050
        // Code size 7 (0x7)
        .maxstack 8

        IL_0000: ldarg.0
        IL_0001: call instance void [mscorlib]System.Object::.ctor()
        IL_0006: ret
    } // end of method C::.ctor

} // end of class A.B.C
Run Code Online (Sandbox Code Playgroud)

然后该类Type具有 aName和 aNamespace属性。类Type(作为 mscorlib 的一个重要部分)对于 CLR 的良好工作是不可或缺的。

那么如果问题是:已编译的 .NET 程序中是否存在显式命名空间?答案是“不”。只有全名。

如果问题是:.NET 中是否存在命名空间的概念(在任何/所有级别)?答案是“是”。它存在于 IL(源代码级别,.namespace)、CLR(.NET API,Type.Namespace)、C#(.NET 的“主要”语言,用于编写几乎所有 .NET 库)中 ( namespace)。

  • 好吧,这使得我们阵营中的 2 个人都认为“存在名称空间”:-) 我相信造成混乱的原因是 OP 明确询问了 IL。这与 IL 无关,而是与 DLL 中包含的具有“特殊”含义的元数据有关,在本例中:点符号表示它是一个命名空间。如果您询问令牌,那么名称空间没有元数据令牌 - 但仅仅因为它们本身没有元数据令牌 ID,并不意味着它们不存在。公平地说,您不能拥有没有类型的命名空间。 (2认同)