Class Attributes

Class Attributes

An earlier section (“Class Metadata”) listed the various pieces of information included in a type definition. In the simplest case, when only the TypeDef metadata table is involved, the ILAsm syntax for a type definition is as follows:

   .namespace <dotted_name> {              .class <flags> <simple_name> extends <class_ref> {                  }   }

The <dotted_name> value specified in the .namespace directive defines the TypeDef ’s Namespace entry, <simple_name> specified in the .class directive defines the TypeDef ’s Name entry, <class_ref> specified in the extends clause defines the Extends entry, and <flags> defines the Flags entry.

Flags

The numerous TypeDef flags can be divided into several groups, as described here.

  • Visibility flags (binary mask 0x00000007):

    1. private (0x00000000)  The type is not visible outside the assembly. This is the default.

    2. public (0x00000001)  The type is visible outside the assembly.

    3. nested public (0x00000002)  The nested type has public visibility.

    4. nested private (0x00000003)  The nested type has private visibility.

    5. nested family (0x00000004)  The nested type has family visibility—that is, it is visible to descendants of the enclosing class only.

    6. nested assembly (0x00000005)  The nested type is visible within the assembly only.

    7. nested famandassem (0x00000006)  The nested type is visible to the descendants of the enclosing class residing in the same assembly.

    8. nested famorassem (0x00000007)  The nested type is visible to the descendants of the enclosing class either within or outside the assembly and to every type within the assembly with no regard to “lineage.”

  • Layout flags (binary mask 0x00000018):

    1. auto (0x00000000)  The type fields are laid out automatically, at the loader’s discretion. This is the default.

    2. sequential (0x00000008)  The loader should preserve the order of the fields.

    3. explicit (0x00000010)  The type layout is specified explicitly, and the loader should follow it. (See Chapter 8, “Fields and Data Constants,” for information on field declaration.)

  • Type semantics flags (binary mask 0x000005A0):

    1. interface (0x00000020)  The type is an interface. If this flag is not specified, the type is presumed to be a class or a value type; if this flag is specified, the default parent is set to nil.

    2. abstract (0x00000080)  The class is abstract—that is, it has abstract member methods. As such, this class cannot be instantiated and can be used only as a parent of another type or types. This flag is invalid for value types.

    3. sealed (0x00000100)  No types can be derived from this type. All value types and enumerators must carry this flag.

    4. specialname (0x00000400)  The type has a special name. How special depends on the name itself. This flag indicates to the metadata API and the loader that the name has a meaning in which they might be interested—for instance, _Deleted*.

  • Type implementation flags (binary mask 0x00103000):

    1. import (0x00001000)  The type (a class or an interface) is imported from a COM type library.

    2. serializable (0x00002000)  The type can be serialized into sequential code by the serializer provided in the Microsoft .NET Framework class library.

    3. beforefieldinit (0x00100000)  The type can be initialized any time before the first access to a static field. If this flag is not set, the type is initialized before the first access to one of its static fields or methods.

  • String formatting flags (binary mask 0x00030000):

    1. ansi (0x00000000)  When interoperating with native methods, the managed strings are by default marshaled to and from ANSI strings. Managed strings are instances of the System.String class defined in the .NET Framework class library. Marshaling is a general term for data conversion on the managed and unmanaged code boundaries. (See Chapter 15, “Managed and Unmanaged Code Interoperation,” for detailed information.) String formatting flags specify only default marshaling and are irrelevant when marshaling is explicitly specified. This flag, ansi, is the default flag for a class and hence represents a “default default” string marshaling.

    2. unicode (0x00010000)  By default, managed strings are marshaled to and from Unicode.

    3. autochar (0x00020000)  The default string marshaling is defined by the underlying platform.

  • Reserved flags (binary mask 0x0004080):

    1. rtspecialname (0x00000800)  The name is reserved by the common language runtime and has a special meaning. This flag is legal only in combination with the specialname flag. The keyword rtspecialname has no effect in ILAsm and is provided for informational purposes only. The IL Disassembler uses this keyword to show the presence of this reserved flag. Reserved flags cannot be set at will—this flag, for example, is set automatically by the metadata emission API when it emits an item with the specialname flag set and the name recognized as specific to the common language runtime.

    2. <no keyword> (0x00040000)  The type has declarative security metadata associated with it. This flag is set by the metadata emission API when respective declarative security metadata is emitted.

  • Semantics pseudoflags (no binary mask)  These are not true binary flags that define the Flags entry of a TypeDef record but rather are lexical pseudoflags modifying the default parent of the class:

    1. value  The type is a value type. The default parent is System.ValueType.

    2. enum  The type is an enumerator. The default parent is System.Enum.

Class References

The nonterminal symbol <class_ref> in the extends clause represents a reference to a type and translates into a TypeDef or a TypeRef. The general syntax of a class reference is as follows:

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

where

   <resolution_scope> ::= [<assembly_ref_alias>]            [.module <module_ref_name>]

Note that the square brackets in the definition of <resolution_scope> are syntactic elements; they do not indicate that any portion of the definition is optional.

Here are a few examples of class references:

   [mscorlib]System.ValueType // Type is defined in another assembly    [.module Second.dll]Foo.Bar // Type is defined in another module    Foo.Baz  // Type is defined in this module

If the resolution scope of a class reference points to an external assembly or module, the class reference is translated into a TypeRef metadata record, with the full type name providing values for the Name and Namespace entries and the resolution scope providing an AssemblyRef or a ModuleRef token for the ResolutionScope entry.

If the resolution scope is not defined—that is, if the referenced type is defined somewhere in the current module—the class reference is translated into the respective TypeDef record.

Parent of the Type

Having resolved the class reference to a TypeRef or TypeDef token, we thus provided the value for the Extends entry of the TypeDef record under construction. This token references the type’s parent—that is, the type from which the current type is derived.

The type referenced in the extends clause must not be sealed and must not be an interface; otherwise, the loader will fail to load the type. When a type is sealed, no types can be derived from it.

If the extends clause is omitted, the ILAsm compiler assigns a default parent depending on the flags specified for the type:

  • Interface  No parent. The interfaces are not derived from other types.

  • value  The parent is [mscorlib]System.ValueType.

  • enum  The parent is [mscorlib]System.Enum.

  • None of the above  The parent is [mscorlib]System.Object.

If the extends clause is present, the value and enum flags are ignored, and the interface flag causes a compilation error.

If the type layout is specified as sequential or explicit, the type’s parent must also have the corresponding layout, unless the parent is [mscorlib]System.Object, [mscorlib]System.ValueType, or [mscorlib]System.Enum. The rationale is that the type might inherit fields from its parent, and the type cannot have a mixed layout—that is, it cannot have some fields laid out automatically and some laid out explicitly or sequentially. However, an auto-layout type can be derived from a type having any layout; in this case, information about the parent’s field layout plays no role in laying out the derived type.

Interface Implementations

If the type being defined implements one or more interfaces, the type declaration has an additional clause, the implements clause, as shown here:

   .namespace <dotted_name> {              .class <flags> <simple_name>          extends <class_ref>           implements <class_refs> {                        }    }

The nonterminal symbol <class_refs> simply means a comma-separated list of class references:

   <class_refs> ::= <class_ref>[,<class_ref>*]

For example:

   .namespace MyNamespace {              .class public MyClass           extends MyNamespace.MyClassBase           implements MyNamespace.IOne,                     MyNamespace.ITwo,                     MyNamespace.IThree {                                }    }

The types referenced in the implements clause must be interfaces. A type implementing an interface must provide implementation for all of the interface’s instance methods. The only exception to this rule is an abstract class.

The implements clause of a type declaration creates as many records in the InterfaceImpl metadata table as there are class references listed in this clause. In our preceding example, three InterfaceImpl records would be created.

Class Layout Information

To provide additional information regarding type layout (field alignment, total type size, or both), you need to use the .pack and .size directives, as shown in this example:

   .namespace MyNamespace {              .class public value explicit MyStruct {          .pack 4          .size 1024                  }    }

The .pack and .size directives appear within the scope of the type declaration, in any order. If .pack is not specified, the field alignment defaults to 1. If .pack or .size is specified, a ClassLayout record is created for this TypeDef.

Integer values specified in a .pack directive must be 0 or a power of 2, in the range 20 to 27 (1 to 128). Breaking this rule results in a compilation error. When the value is 0, the field alignment defaults to the value defined by the underlying platform.

Class layout information should not be specified for the auto-layout types. Formally, defining the class layout information for an auto-layout type represents invalid metadata. In reality, however, it is simply a waste of metadata space; when the loader encounters an auto-layout type, it never checks to see whether this type has a corresponding ClassLayout record.



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