Nested Types

Nested Types

Nested types are types (classes, interfaces, value types) that are defined within other types. However, being defined within another type does not make the nested type anything like the member classes or inner classes. The instance pointers (this) of a nested type and its enclosing type are in no way related. A nested class does not automatically get access to the this pointer of its enclosing class when the instance of the enclosing class is created.

In addition, instantiation of the enclosing class does not involve instantiation of the class(es) nested in it. The nested classes must be instantiated separately. Instantiation of a nested class does not require the enclosing class to be instantiated.

Type nesting is not about membership and joint instantiation; rather, it’s all about visibility. As explained earlier in “Class Attributes,” nested types at any level of nesting have their own specific visibility flags. When one type is nested in another type, the visibility of the nested type is “filtered” by the visibility of the enclosing type. If, for example, a class whose visibility is set to nested public is nested in a private class, this nested class will not be visible outside the assembly despite its own specified visibility.

This visibility filtering works throughout all levels of nesting. The final visibility of a nested class is defined by its own declared visibility and then is limited in sequence by the visibilities of all classes enclosing it, directly or indirectly.

Nested classes are defined in ILAsm the same way they are defined in other languages—that is, the nested classes are declared within the lexical scope of their encloser declaration:

.namespace MyNS {    .class public Encl {              .class nested public Nestd1 {                    .class nested family Nestd2 {                       }       }    } }

According to this declaration, the Nestd2 class is nested in the Nestd1 class, which in turn is nested in MyNS.Encl, which is not a nested class.

Because nested classes belong to their enclosers rather than to namespaces, a nested class name is always the full name. Having said that, let’s return for a moment to the experiment with dotted class names described earlier in this chapter, in the section “Full Class Names.” In that case, we defined a class with a dotted name, only to find that the left part of the dotted name was moved to the namespace by the metadata emission API. The same thing will happen if we try to define a nested class with a dotted name. Although this “name redistribution” has no ill effect on the top-level classes, which are always referenced by their full names, it does have quite an effect on nested classes, which are not supposed to have namespaces and are addressed by name only. Don’t use dotted names for nested classes.

While on the subject of referencing the classes, let’s see how the nested classes are referenced in ILAsm:

   <nested_class_ref> ::= <encloser_ref> <simple_name>

where

   <encloser_ref> ::= <nested_class_ref>    <class_ref>

and <class_ref> has already been defined earlier as follows:

   <class_ref> ::= [<resolution_scope>]<full_type_name>

According to these definitions, classes Nestd1 and Nestd2 will be referenced respectively as MyNS.Encl/Nestd1 and MyNS.Encl/Nestd1/Nestd2. Names of nested classes must be unique within their nester, as opposed to the full names of top-level classes, which must be unique within the module or (for public classes) within the assembly.

Unlike Microsoft Visual C# .NET, which uses a dot delimiter for all hierarchical relationships without discrimination—so that One.Two.Three might mean “class Three of namespace One.Two” or “class Three nested in class Two of namespace One” or even “field Three of class Two nested in class One”—ILAsm uses different delimiters for different hierarchies. A dot is used for the full class name hierarchy; a forward slash (/) indicates the nesting hierarchy; and a double colon (::), as in C++, denotes the class-member relationship.

Thus far, the discussion has focused mainly on what nested classes are not. One more important negative to note: nested classes have no effect on the layout of their enclosers. If you want to declare a substructure of a structure, you must declare a nested value type (substructure) within the enclosing value type (structure) and then define a field of the substructure type:

   .class public value Struct {              .class nested public value Substruct {                 }       .field public valuetype Struct/Substruct Substr    }

Now I need to say something positive about nested classes. Members of a nested class have access to all members of the enclosing class without exception, including access to private members. In this regard, the nesting relationship is even stronger than inheritance and stronger than the member class relationship in C++, where member classes don’t have access to private members of their owner. Of course, to get access to the encloser’s instance members, the nested type members should first obtain the instance pointer to the encloser. This “full disclosure” policy works one-way only; the encloser has no access to private members of the nested class.

Nested types can be used as base classes for other types that don’t need to be nested:

   .class public X {              .class nested public Y {                 }    }    .class public extends X/Y {           }

Of course, class Z, derived from a nested class (Y), does not have any access rights to private members of the encloser (X). The “full disclosure” privilege is not inheritable.

A nested class can be derived from its encloser. In this case, it retains access to the encloser’s private members, and it also acquires an ability to override the encloser’s virtual methods. The enclosing class cannot be derived from any of its nested classes.

note

A metadata validity rule states that a nested class must be defined in the same module as its encloser. In ILAsm, however, the only way to define a nested class is to declare it within the encloser’s lexical scope, which means that you could not violate this validity rule in ILAsm even if you tried.



Inside Microsoft. NET IL Assembler
Inside Microsoft .NET IL Assembler
ISBN: 0735615470
EAN: 2147483647
Year: 2005
Pages: 147
Authors: SERGE LIDIN

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net