Is C# namespace compiled into IL files to be "complete" names?

700 views Asked by At

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?

4

There are 4 answers

1
xanatos On BEST ANSWER

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
bot_insane On

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.

6
stakx - no longer contributing On

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).

0
atlaste On

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.