问题
E.g, if I have
namespace a
namespace b
{
class C...
class D...
}
So after compiling, in IL file, where's the namespace information? Do I get two classes named a.b.C and a.b.D where the class names is prefixed by the namespace name?
Or I get a namespace a.b in the assembly file and having class C/class D inside it, just like C# code?
回答1:
The other two responses wrote something, so I have to write the opposite :-)
Let's say that Microsoft kept the foot in both camps... Reading the ECMA-335:
Page 114
While some programming languages introduce the concept of a namespace, the only support in the CLI for this concept is as a metadata encoding technique. Type names are always specified by their full name relative to the assembly in which they are defined.
But then even this ECMA standard uses freely the namespace concept:
In order to prevent name collisions into the future, all custom attributes in the System namespace are reserved for standardization.
And the IL language supports the .namespace
instruction, that is equivalent to the namespace instruction of C# (this instruction is named in the ECMA standard but there are no examples. The ILASM compiles correctly this example and the decompiled code is what one would expect)...
.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
}
}
But note that the generated code is equivalent to not using .namespace
and including directly the full name in the .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
And then the Type
class has a Name
and a Namespace
properties. And the Type
class (as a big piece of mscorlib) is integral to the good working of the CLR.
So if the question is: is there an explicit namespace in a compiled .NET program? The response is "no". There is only fullnames.
If the question is: is there the concept of namespace in .NET (at any/all levels)? The response is "yes". It is present both in IL (source code level, .namespace
), CLR (.NET API, Type.Namespace
), C# (the "main" language of .NET, used to write nearly all the .NET libraries) (namespace
).
回答2:
The CLR doesn’t know anything about namespaces. When you access a type, the CLR needs to know the full name of the type and which assembly contains the definition of the type so that the runtime can load the proper assembly, find the type, and manipulate it.
It mean that your class C
in namespace b
is stored like b.C
.
回答3:
Namespaces do not exist in IL. They are not preserved as metadata. In IL, all references to types and methods must be made using fully-qualified names.
IL, however, recognises and explicitly allows that a type name contain dots. C# or VB.NET namespaces are a language construct built on top of that: They are essentially a mechanism that allows you to only specify the latter dot-separated parts of a type name. using
or namespace Imports
directives are hints to the compilers for guessing the former parts of incomplete type names; but in all cases, the compiler has to translate non-fully-qualified names (SomeType
) to fully-qualified type names (SomeNamespace.SomeType
).
回答4:
Let's get something straight first.
- IL is basically just the 'basic building block' language used in .NET
- A DLL contains IL and metadata
You can see both if you fire up ildasm
(from a visual studio command prompt), put your DLL in there, dump everything and then browse it in your favorite text editor. That'll contain both the metadata and the IL code.
IL doesn't contain namespace info, it's just composed of 'tokens', which are basically ID's to classes, functions, etc. These ID's can be resolved.
One of the things in a DLL is the metadata container for a namespace. Or as ILDASM will show you:
// ================================= 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)
Now, what you basically call a namespace is the collection of typedefs metadata tokens that start with the same 'dot' prefix. A namespace isn't really an 'entity', which means it has no token by itself. A namespace only exists because there are names of the types that include dots (which do have tokens). In other words, a namespace doesn't exist directly; it's derived from the types that are there.
Now, knowing this, your question can easily be answered:
So after compiling, in IL file, where's the namespace information? Do I get two classes named a.b.C and a.b.D where the class names is prefixed by the namespace name?
Yes, and without them, the namespace wouldn't exist.
来源:https://stackoverflow.com/questions/30797415/is-c-sharp-namespace-compiled-into-il-files-to-be-complete-names