views:

184

answers:

2

Hello,

class name: MyAssembly.MyClass+MyOtherClass

The problem is obviously the + as separator, instead of traditionnal dot, its function, and to find official documentation to see if others separators exist

Thank you in advance !

+8  A: 

This is what the compiler uses in the metadata to represent a nested class.

i.e.

class A { class B {} }

would be seen as

class A+B

in the metadata

Ben Voigt
thank you. This is the only one sign we could find in this way ?
Graveen
I was just looking at the .NET (1.1) library in ILDASM and the nested types in there showed '/' as the separator.
Conrad Albrecht
So ILDASM is lying.
Ben Voigt
@Ben - ILDASM isn't lying, exactly; there's just a different type name grammar for CIL than for Reflection. See my comment on Jon's post.
kvb
@kvb: One of those names is more significant than the others, because it is exposed regardless of language: the reflected name. All the other names are language-specific. "X.Y" isn't THE "lexical name", it's only A lexical name (another lexical name is "X::Y", courtesy of C++/CLI, and "X/Y" is a lexical name as well, from IL). The word "lexical" should have been a big clue about that, since lexing is a language-centric task.
Ben Voigt
@Ben - That's fair enough; take it up with the spec writer :) I'm just quoting their table. In any case, I think it's a bit over the top to claim that ILDASM is "lying". It just has its own type grammar.
kvb
+11  A: 

That's just the way that a nested type is represented. So for example:

namespace Foo
{
    class Outer
    {
        class Nested {}
    }
}

will create a type with a full name of Foo.Outer+Nested in the compiled code. (So that's what typeof(Outer.Nested).FullName would return, for example.)

It's not clear to me whether this is specified behaviour, or just what the Microsoft C# compiler chooses to use; it's an "unspeakable" name in that you couldn't explicitly declare a class with a + in it in normal C#, so the compiler knows it won't clash with anything else. Section 10.3.8 of the C# 3 spec doesn't dictate the compiled name as far as I can see.

EDIT: I've just seen that Type.AssemblyQualifiedName specifies that "+" is used to precede a nested type name... but it's still not clear whether or not that's actually required or just conventional.

Jon Skeet
Another way this implementation detail manifests itself is in nested generic types. If you have class Outer<T> with nested class Inner<U> you'll see that what you actually get in metadata are two types, Outer<`1> and Outer+Inner<`2>. Nested types are from the CLR perspective really just a convenient fib told by the language. The nesting is manifested "for real" pretty much only in the ability for the inner type to access the private members of the outer type. (Namespaces are similarly a fiction.)
Eric Lippert
If the name of the nested class was simply chosen by Microsoft's C# compiler how would interoperability with other compilers be possible? Does it mean that one cannot use nested classes if e.g. using the Mono compiler?
0xA3
divo: I would assume that Mono's C# compiler follows the same scheme as Microsoft's. Likewise anywhere else where something is left unspecified in the C# spec.
Chris Charabaruk
@divo: Like Chris, I strongly suspect that Mono follows the same scheme as the MS compiler. However, in most cases this won't be noticeable anyway - it's only if you actually need to refer to a type by its full name *as a string*. I don't do that very often...
Jon Skeet
@divo: I think what Jon is getting at is that types are referenced by metadata tokens, not by name, in the actual IL. So even a platform using a different rule for name mangling would still be able to execute code compiled by the Microsoft C# compiler.
Ben Voigt
@Eric: Do nested types get the special access by virtue of the name or is there a field in the metadata for this? Could this field be used to create "friend classes" ala C++?
Ben Voigt
@Ben: The nestedness of a type is in the metadata. An interesting fact about the verifier is that if class D overrides virtual method B.M from D's base class B, then D is allowed to do a non-virtual "base" call to B.M. However, code outside of B's type hierarchy is NOT allowed to do that, even if the code is a nested type D.C!
Eric Lippert
@Eric: Isn't that a consequence of only being allowed to do a non-virtual call to a base method on "this"? That's completely outside the access modifiers, any member of a class (however nested) can access private members of ANY instance of that class. But IIRC calls to base methods have to be done on the same instance as "this". Anyway, could the nestedness metadata be used to implement friend classes, that is to give another class access to one's private members? Would such a scheme be restricted to a single relationship? Or would it be transitive unlike C++ friend?
Ben Voigt
Section 10.7.2 of the ECMA CLI spec mentions that "While a type name encoded in metadata does not explicitly mention its enclosing type, the CIL and Reflection type name grammars do include this detail", followed by a table of examples which includes the lexical name (e.g. `X.Y`) the metadata encoding (e.g. `Y`), the CIL name (e.g. `X/Y`) and the Reflection name (e.g. `X+Y`).
kvb
@Jon: exactly, the code where i find this syntax was a database entry where the class type is stored - as a string. I first assumed the class type was parsed then instanced via reflexion, and as i could not find the parsing sequence, someone pointed me it could be a part of C# syntax.
Graveen