例如,如果我有
namespace a
namespace b
{
class C...
class D...
}
编译之后,在IL文件中,命名空间信息在哪里?我是否得到两个名为a.b.C和a.b.D的类,其中类名以名称空间名称作为前缀?
或者我在汇编文件中得到一个命名空间a.b,里面有C / D类,就像C#代码一样?
答案 0 :(得分:5)
CLR对名称空间一无所知。当您访问类型时,CLR 需要知道类型的全名和 哪个程序集包含类型的定义,以便运行时可以加载正确的程序集, 找到类型并操纵它。
这意味着class C
中namespace b
的存储方式与b.C
一样。
答案 1 :(得分:3)
其他两个回答写了一些东西,所以我必须写相反的东西: - )
让我们说微软一直在两个阵营中徘徊......阅读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
}
}
但请注意,生成的代码相当于不使用.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
然后Type
类具有Name
和Namespace
属性。而Type
类(作为mscorlib的一大块)对于CLR的良好工作是不可或缺的。
因此,如果问题是:编译的.NET程序中是否有明确的命名空间?答案是" no"。只有全名。
如果问题是:.NET中是否存在命名空间的概念(在任何/所有级别)?答案是"是"。它存在于IL(源代码级别,.namespace
),CLR(.NET API,Type.Namespace
),C#("主要" .NET语言,用于编写)中几乎所有的.NET库)(namespace
)。
答案 2 :(得分:1)
IL中不存在命名空间。它们不会保留为元数据。在IL中,必须使用完全限定名称来对类型和方法进行所有引用。
然而, IL识别并明确允许类型名称包含点。 C#或VB.NET命名空间是构建在其上的语言构造:它们本质上是一种机制,允许您仅指定类型名称的后面的点分隔部分。 using
或命名空间Imports
指令是编译器猜测不完整类型名称的前部分的提示;但在所有情况下,编译器必须将非完全限定名称(SomeType
)转换为完全限定类型名称(SomeNamespace.SomeType
)。
答案 3 :(得分:1)
让我们先做点准备。
如果你启动ildasm
(从visual studio命令提示符),你可以看到两者,把你的DLL放在那里,转储所有内容,然后在你喜欢的文本编辑器中浏览它。这将包含元数据和IL代码。
IL不包含命名空间信息,它只是由“令牌”组成,它们基本上是类,功能等的ID。这些ID' s可以解决。
DLL中的一个功能是命名空间的元数据容器。或者正如ILDASM将向您展示:
// ================================= M E T A I N F O ================================
// ===========================================================
// ScopeName : MyNamespace
// MVID : {22EE923F-126A-43BA-8A72-59A7A069625A}
// ===========================================================
// Global functions
// -------------------------------------------------------
//
// Global fields
// -------------------------------------------------------
//
// Global MemberRefs
// -------------------------------------------------------
//
// TypeDef #1 (02000002)
// -------------------------------------------------------
// TypDefName: MyNamespace.MyType (02000002)
// Flags : [Public] [AutoLayout] [Class] [AnsiClass] (00000001)
// Extends : 01000001 [TypeRef] System.Object
// Field #1 (04000001)
现在,你基本上称之为命名空间的是typedef元数据标记的集合,它们以相同的'点'开头。字首。命名空间实际上并不是一个“实体”,这意味着它本身没有令牌。仅存在命名空间,因为存在包含点(具有令牌)的类型的名称。换句话说,命名空间并不直接存在;它来自那里的类型。
现在,知道这一点,你的问题很容易回答:
编译后,在IL文件中,命名空间信息在哪里?做 我得到两个名为a.b.C和a.b.D的类,其中类名是 以命名空间名称?
为前缀
是的,没有它们,命名空间就不存在了。