21 Metadata Logical Format: Tables


This section defines the structures that describe metadata, and how they are cross-indexed. This corresponds to how metadata is laid out, after being read into memory from a PE file. (For a description of metadata layout inside the PE file itself, see Partition II, section 23.)

Metadata is stored in two kinds of structures tables (arrays of records) and heaps. There are four heaps in any module: String, Blob, Userstring, and Guid. The first three are byte arrays (so valid indices into these heaps might be 0, 23, 25, 39, etc.). The Guid heap is an array of GUIDs, each 16 bytes wide. Its first element is numbered 1, its second 2, and so on.

Each entry in each column of each table is either a constant or an index.

Constants are either literal values (e.g., ALG_SID_SHA1 = 4, stored in the HashAlgId column of the Assembly table), or, more commonly, bitmasks. Most bitmasks (they are almost all called "Flags") are 2 bytes wide (e.g., the Flags column in the Field table), but there are a few that are 4 bytes (e.g., the Flags column in the TypeDef table).

Each index is either 2 bytes wide or 4 bytes wide. The index points into another (or the same) table, or into one of the four heaps. The size of each index column in a table is only made 4 bytes if it needs to be, for that particular module. So, if a particular column indexes a table, or tables, whose highest row number fits in a 2-byte value, the indexer column need only be 2 bytes wide. Conversely, for huge tables, containing 64K rows or more, an indexer of that table will be 4 bytes wide.

Note that indices begin at 1, meaning the first row in any given metadata table. An index value of zero denotes that it does not index a row at all (it behaves like a null reference).

The columns that index a metadata table are of two sorts:

  • Simple that column indexes one, and only one, table. For example, the FieldList column in the TypeDef table always indexes the Field table. So all values in that column are simple integers, giving the row number in the target table.

  • Coded that column indexes any of several tables. For example, the Extends column in the TypeDef table can index into the TypeDef table or into the TypeRef table. A few bits of that index value are reserved to define which table it targets. For the most part, this specification talks of index values after being decoded into row numbers within the target table. However, the specification includes a description of these coded indices in the section that describes the physical layout of metadata (Partition II, section 23).

Metadata preserves name strings, as created by a compiler or code generator, unchanged. Essentially it treats each string as an opaque "blob." In particular, it preserves case. The CLI imposes no limit on the size of names stored in metadata and subsequently processed by the CLI.

ANNOTATION

Implementation-Specific (Microsoft): For first release, strings are limited in length. Depending on its purpose, a string can be no larger than MAX_CLASS_NAME (defined as 1024) or MAX_PATH_NAME (defined as 260). These values refer to the maximum number of bytes that the string, after being converted into UTF8 format, may occupy; that includes a terminating null character. It is intended that this limitation be removed in a future release. Within this document, the above restrictions are abbreviated to the phrase "is limited to MAX_CLASS_NAME" or "is limited to MAX_PATH_NAME".


Matching AssemblyRefs and ModuleRefs to their corresponding Assembly and Module shall be performed case-blind. However, all other name matches (type, field, method, property, event) are exact so that this level of resolution is the same across all platforms, whether their OS is case-sensitive or not.

Tables are given both a name (e.g., "Assembly") and a number (e.g., 0x20). The number for each table is listed immediately with its title in the following sections.

A few of the tables represent extensions to regular CLI files. Specifically, ENCLog and ENCMap, which occur in temporary images, generated during "Edit and Continue" or "incremental compilation" scenarios, while debugging. Both table types are reserved for future use.

References to the methods or fields of a Type are stored together in a metadata table called the MemberRef table. However, sometimes, for clearer explanation, this specification distinguishes between these two kinds of references, calling them "MethodRef" and "FieldRef."

Certain tables are required to be sorted by a primary key, as follows:

Table

Primary Key Column

Constant

Parent

FieldMarshal

Parent

MethodSemantics

Association

ClassLayout

Parent

FieldLayout

Field

ImplMap

MemberForwarded

FieldRVA

Field

NestedClass

NestedClass

MethodImpl

Class

CustomAttribute

Parent

DeclSecurity

Parent

Furthermore, the InterfaceImpl table is subsorted using the Interface column as a secondary key.

Finally, the TypeDef table has a special ordering constraint: the definition of an enclosing class must precede the definition of all classes it encloses.

21.1 Metadata Validation Rules

This contains informative text only.


The sections that follow describe the schema for each kind of metadata table and explain the detailed rules that guarantee [that] metadata emitted into any PE file is valid. Checking that metadata is valid ensures that later processing checking the CIL instruction stream for type safety, building method tables, CIL-to-native-code compilation, data marshalling, etc. will not cause the CLI to crash or behave in an insecure fashion.

In addition, some of the rules are used to check compliance with the CLS requirements (see Partition I, section 11) even though these are not related to valid metadata. These are marked with a trailing [CLS] tag.

The rules for valid metadata refer to an individual module. A module is any collection of metadata that could typically be saved to a disk file. This includes the output of compilers and linkers, or the output of script compilers (where often the metadata is held only in memory, but never actually saved to a file on disk).

The rules address intra-module validation only. So, validator software, for example, that checks conformance with this spec, need not resolve references or walk type hierarchies defined in other modules. However, it should be clear that even if two modules, A and B, analyzed separately, contain only valid metadata, they may still be in error when viewed together (e.g., a call from module A, to a method defined in module B, might specify a call-site signature that does not match the signatures defined for that method in B).

All checks are categorized as ERROR, WARNING, or CLS.

  • An ERROR reports something that might cause a CLI to crash or hang, might run but produce wrong answers, or might be entirely benign. There may exist conforming implementations of the CLI that will not accept metadata that violates an ERROR rule, and therefore such metadata is invalid and is not portable.

  • A WARNING reports something, not actually wrong, but possibly a slip on the part of the compiler. Normally, it indicates a case where a compiler could have encoded the same information in a more compact fashion or where the metadata represents a construct that can have no actual use at runtime. All conforming implementations will support metadata that violates only WARNING rules; hence such metadata is both valid and portable.

  • A CLS reports lack of compliance with the Common Language Specification (see Partition I [section 7]). Such metadata is both valid and portable, but there may exist programming languages that cannot process it, even though all conforming implementations of the CLI support the constructs.

Validation rules fall into a few broad categories, as follows:

  • Number of Rows: A few tables are allowed only one row (e.g., the Module table). Most have no such restriction.

  • Unique Rows: No table may contain duplicate rows, where "duplicate" is defined in terms of its key column, or combination of columns.

  • Valid Indices: Columns which are indices shall point somewhere sensible, as follows:

    • Every index into the String, Blob, or Userstring heaps shall point into that heap, neither before its start (offset 0), nor after its end.

    • Every index into the Guid heap shall lie between 1 and the maximum element number in this module, inclusive.

    • Every index (row number) into another metadata table shall lie between 0 and that table's row count + 1 (for some tables, the index may point just past the end of any target table, meaning it indexes nothing).

  • Valid Bitmasks: Columns which are bitmasks shall only have valid permutations of bits set.

  • Valid RVAs: There are restrictions upon fields and methods that are assigned RVAs (Relative Virtual Addresses; these are byte offsets, expressed from the address at which the corresponding PE file is loaded into memory).

Note that some of the rules listed below say "nothing" for example, some rules state that a particular table is allowed zero or more rows so there is no way that the check can fail. This is done simply for completeness, to record that such details have indeed been addressed, rather than overlooked.

End informative text


The CLI imposes no limit on the size of names stored in metadata and subsequently processed by a CLI implementation.

21.2 Assembly: 0x20

The Assembly table has the following columns:

  • HashAlgId (a 4-byte constant of type AssemblyHashAlgorithm; see Partition II, section 22.1.1)

  • MajorVersion, MinorVersion, BuildNumber, RevisionNumber (2-byte constants)

  • Flags (a 4-byte bitmask of type AssemblyFlags; see Partition II, section 22.1.2)

  • PublicKey (index into Blob heap)

  • Name (index into String heap)

  • Culture (index into String heap)

The Assembly table is defined using the .assembly directive (see Partition II, section 6.2); its columns are obtained from the respective .hash algorithm, .ver, .publickey, and .culture [directives] (see Partition II, section 6.2.1). For an example, see Partition II, section 6.2.

This contains informative text only.


  1. The Assembly table may contain zero or one row. [ERROR]

  2. HashAlgId should be one of the specified values. [ERROR]

    ANNOTATION

    Implementation-Specific (Microsoft): The Microsoft implementation treats this as a WARNING rather than an error, using numbers based on the Crypto APIs. This means that the Microsoft implementation can handle additional algorithms based on the constants of type ALG_CLASS_HASH in WinCrypt.h, as well as those dynamically discovered at runtime.


  3. Flags may have only those values set that are specified. [ERROR]

  4. PublicKey may be null or non-null.

  5. Name shall index a non-null string in the String heap. [ERROR]

  6. The string indexed by Name can be of unlimited length.

  7. Culture may be null or non-null.

  8. If Culture is non-null, it shall index a single string from the list specified (see Partition II, section 22.1.3). [ERROR]

NOTE

Name is a simple name (e.g., "Foo" no drive letter, no path, no file extension); on POSIX-compliant systems, Name contains no colon, no forward-slash, no backslash, no period.


End informative text


21.3 AssemblyOS: 0x22

The AssemblyOS table has the following columns:

  • OSPlatformID (a 4-byte constant)

  • OSMajorVersion (a 4-byte constant)

  • OSMinorVersion (a 4-byte constant)

This record should not be emitted into any PE file. If present in a PE file, it should be treated as if all its fields were zero. It should be ignored by the CLI.

21.4 AssemblyProcessor: 0x21

The AssemblyProcessor table has the following column:

  • Processor (a 4-byte constant)

This record should not be emitted into any PE file. If present in a PE file, it should be treated as if its field were zero. It should be ignored by the CLI.

21.5 AssemblyRef: 0x23

The AssemblyRef table has the following columns:

  • MajorVersion, MinorVersion, BuildNumber, RevisionNumber (2-byte constants)

  • Flags (a 4-byte bitmask of type AssemblyFlags; see Partition II, section 22.1.2)

  • PublicKeyOrToken (index into Blob heap the public key or token that identifies the author of this assembly)

  • Name (index into String heap)

  • Culture (index into String heap)

  • HashValue (index into Blob heap)

The table is defined by the .assembly extern directive (see Partition II, section 6.3). Its columns are filled using directives similar to those of the Assembly table, except for the PublicKeyOrToken column, which is defined using the .publickeytoken directive. For an example, see Partition II, section 6.3.

This contains informative text only.


  1. MajorVersion, MinorVersion, BuildNumber, RevisionNumber can each have any value.

  2. Flags may have only one possible bit set the PublicKey bit (see Partition II, section 22.1.2). All other bits shall be zero. [ERROR]

  3. PublicKeyOrToken may be null or non-null (note that the Flags.PublicKey bit specifies whether the "blob" is a full public key or the short hashed token).

  4. If non-null, then PublicKeyOrToken shall index a valid offset in the Blob heap. [ERROR]

  5. Name shall index a non-null string, in the String heap (there is no limit to its length). [ERROR]

  6. Culture may be null or non-null. If non-null, it shall index a single string from the list specified (see Partition II, section 22.1.3). [ERROR]

  7. HashValue may be null or non-null.

  8. If non-null, then HashValue shall index a non-empty "blob" in the Blob heap. [ERROR]

  9. The AssemblyRef table shall contain no duplicates, where duplicate rows have the same MajorVersion, MinorVersion, BuildNumber, RevisionNumber, PublicKeyOrToken, Name, and Culture [values]. [WARNING]

NOTE

Name is a simple name (e.g., "Foo" no drive letter, no path, no file extension); on POSIX-compliant systems, Name contains no colon, no forward-slash, no backslash, no period.


End informative text


21.6 AssemblyRefOS: 0x25

The AssemblyRefOS table has the following columns:

  • OSPlatformId (4-byte constant)

  • OSMajorVersion (4-byte constant)

  • OSMinorVersion (4-byte constant)

  • AssemblyRef (index into the AssemblyRef table)

These records should not be emitted into any PE file. If present in a PE file, they should be treated as if their fields were zero. They should be ignored by the CLI.

21.7 AssemblyRefProcessor: 0x24

The AssemblyRefProcessor table has the following columns:

  • Processor (4-byte constant)

  • AssemblyRef (index into the AssemblyRef table)

These records should not be emitted into any PE file. If present in a PE file, they should be treated as if their fields were zero. They should be ignored by the CLI.

21.8 ClassLayout: 0x0F

The ClassLayout table is used to define how the fields of a class or value type shall be laid out by the CLI (normally, the CLI is free to reorder and/or insert gaps between the fields defined for a class or value type).

RATIONALE

This feature is used to make a managed value type be laid out in exactly the same way as an unmanaged C struct with this condition true, the managed value type can be handed to unmanaged code, which accesses the fields exactly as if that block of memory had been laid out by unmanaged code.


The information held in the ClassLayout table depends upon the Flags value for {AutoLayout, SequentialLayout, ExplicitLayout} in the owner class or value type.

A type has layout if it is marked SequentialLayout or ExplicitLayout. If any type within an inheritance chain has layout, then so shall all its parents, up to the one that descends immediately from System.Object, or from System.ValueType.

This contains informative text only.


Layout cannot begin partway down the chain. But it is legal to stop "having layout" at any point down the chain.

For example, in the diagrams below, class A derives from System.Object; class B derives from A; class C derives from B. System.Object has no layout. But A, B, and C are all defined with layout, and that is legal.

graphics/05inf01.gif

Similarly with classes E, F, and G, G has no layout. This, too, is legal. The following picture shows two illegal setups:

graphics/05inf02.gif

On the left, the "chain with layout" does not start at the "highest" class. And on the right, there is a "hole" in the "chain with layout."

Layout information for a class or value type is held in two tables the ClassLayout and FieldLayout tables, as shown in this diagram:

graphics/05inf03.gif

This example shows how row 3 of the ClassLayout table points to row 2 in the TypeDef table (the definition for a Class, called "MyClass"). Rows 4 through 6 of the FieldLayout table point to corresponding rows in the Field table. This illustrates how the CLI stores the explicit offsets for the three fields that are defined in "MyClass" (there is always one row in the FieldLayout table for each field in the owning class or value type). So, the ClassLayout table acts as an extension to those rows of the TypeDef table that have layout info; since many classes do not have layout info, this design overall saves space.

End informative text


The ClassLayout table has the following columns:

  • PackingSize (a 2-byte constant)

  • ClassSize (a 4-byte constant)

  • Parent (index into TypeDef table)

The rows of the ClassLayout table are defined by placing .pack and .size directives on the body of a parent type declaration (see Partition II, section 9.2). For an example, see Partition II, section 9.7.

This contains informative text only.


  1. A ClassLayout table may contain zero or more or rows.

  2. Parent shall index a valid row in the TypeDef table, corresponding to a Class or ValueType (not to an Interface). [ERROR]

  3. The Class or ValueType indexed by Parent shall not be AutoLayout i.e., it shall be one of SequentialLayout or ExplicitLayout. (See Partition II, section 22.1.14.) Put another way, AutoLayout types shall not own any rows in the ClassLayout table. [ERROR]

  4. If Parent indexes a SequentialLayout type, then: [ERROR]

    • PackingSize shall be one of {0, 1, 2, 4, 8, 16, 32, 64, 128} (0 means use the default pack size for the platform that the application is running on).

    • If ClassSize is non-zero, then it shall be greater than or equal to the calculated size of the class, based upon its field sizes and PackingSize (compilers request padding at the end of a class by providing a value for ClassSize that is larger than its calculated size). [ERROR]

    • A ClassSize of zero does not mean the class has zero size. It means that no size was specified at definition time. Instead, the actual size is calculated from the field types, taking account of packing size (default or specified) and natural alignment on the target, runtime platform.

    • If Parent indexes a ValueType, then ClassSize shall be less than 1 MByte (0x100000 bytes).

    ANNOTATION

    Implementation-Specific (Microsoft): Current implementation of desktop CLI allows 0x3F0000 bytes, but this size may be reduced in future.


  5. Note that ExplicitLayout types might result in verifiable types, so long as that layout does not create union types.

  6. If Parent indexes an ExplicitLayout type, then: [ERROR]

    • If ClassSize is non-zero, then it shall be greater than or equal to the calculated size of the class, based upon the rows it owns in the FieldLayout table (compilers create padding at the end of a class by providing a value for ClassSize that is larger than its calculated size).

    • A ClassSize of zero does not mean the class has zero size. It means that no size was specified at definition time. Instead, the actual size is calculated from the field types, their specified offsets, and any beyond-end alignment packing performed by the target platform.

    • If Parent indexes a ValueType, then ClassSize shall be less than 1 MByte (0x100000 bytes).

      ANNOTATION

      Implementation-Specific (Microsoft): Current implementation allows 0x3F0000 bytes, but this size may be reduced in future.


    • PackingSize shall be 0 (because it makes no sense to provide explicit offsets for each field, as well as a packing size).

  7. Layout along the length of an inheritance chain shall follow the rules specified above (starts at "highest" Type, with no "holes", etc.). [ERROR]

End informative text


21.9 Constant: 0x0B

The Constant table is used to store compile-time, constant values for fields, parameters, and properties.

The Constant table has the following columns:

  • Type (a 1-byte constant, followed by a 1-byte padding zero); see Partition II, section 22.1.15. The encoding of Type for the nullref value for <fieldInit> in ilasm (see Partition II, section 15.2) is ELEMENT_TYPE_CLASS with a Value of a 4-byte zero. Unlike uses of ELEMENT_TYPE_CLASS in signatures, this one is not followed by a type token.

  • Parent (index into the Param or Field or Property table; more precisely, a HasConstant coded index).

  • Value (index into Blob heap).

Note that Constant information does not directly influence runtime behavior, although it is visible via reflection (and hence may be used to implement functionality such as that provided by System.Enum.ToString). Compilers inspect this information, at compile time, when importing metadata; but the value of the constant itself, if used, becomes embedded into the CIL stream the compiler emits. There are no CIL instructions to access the Constant table at runtime.

A row in the Constant table for a parent is created whenever a compile-time value is specified for that parent. For an example, see Partition II, section 15.2.

This contains informative text only.


  1. Type shall be exactly one of: ELEMENT_TYPE_BOOLEAN, ELEMENT_TYPE_CHAR, ELEMENT_TYPE_I1, ELEMENT_TYPE_U1, ELEMENT_TYPE_I2, ELEMENT_TYPE_U2, ELEMENT_TYPE_I4, ELEMENT_TYPE_U4, ELEMENT_TYPE_I8, ELEMENT_TYPE_U8, ELEMENT_TYPE_R4, ELEMENT_TYPE_R8, ELEMENT_TYPE_STRING; or ELEMENT_TYPE_CLASS with a Value of zero (see Partition II, section 22.1.15). [ERROR]

  2. Type shall not be any of: ELEMENT_TYPE_I1, ELEMENT_TYPE_U2, ELEMENT_TYPE_U4, ELEMENT_TYPE_U8 (see , Partition II section 22.1.15). [CLS]

  3. Parent shall index a valid row in the Field or Property or Param table. [ERROR]

  4. There shall be no duplicate rows, based upon Parent. [ERROR]

  5. Constant.Type must match exactly the declared type of the Param, Field, or Property identified by Parent (in the case where the parent is an enum, it must match exactly the underlying type of that enum). [CLS]

End informative text


21.10 CustomAttribute: 0x0C

The CustomAttribute table has the following columns:

  • Parent (index into any metadata table, except the CustomAttribute table itself; more precisely, a HasCustomAttribute coded index)

  • Type (index into the MethodDef or MethodRef table; more precisely, a CustomAttributeType coded index)

  • Value (index into Blob heap)

The CustomAttribute table stores data that can be used to instantiate a Custom Attribute (more precisely, an object of the specified Custom Attribute class) at runtime. The column called Type is slightly misleading it actually indexes a constructor method the owner of that constructor method is the Type of the Custom Attribute.

A row in the CustomAttribute table for a parent is created by the .custom attribute, which gives the value of the Type column and optionally that of the Value column (see Partition II, section 20).

This contains informative text only.


All binary values are stored in little-endian format (except PackedLen items used only as counts for the number of bytes to follow in a UTF8 string).

  1. It is legal for there to be no CustomAttribute present at all that is, for the CustomAttribute.Value field to be null.

  2. Parent can be an index into any metadata table, except the CustomAttribute table itself. [ERROR]

  3. Type shall index a valid row in the Method or MethodRef table. That row shall be a constructor method (for the class of which this information forms an instance). [ERROR]

  4. Value may be null or non-null.

  5. If Value is non-null, it shall index a "blob" in the Blob heap. [ERROR]

  6. The following rules apply to the overall structure of the Value "blob" (see Partition II, section 22.3):

    • Prolog shall be 0x0001. [ERROR]

    • There shall be as many occurrences of FixedArg as are declared in the constructor method. [ERROR]

    • NumNamed may be zero or more.

    • There shall be exactly NumNamed occurrences of NamedArg. [ERROR]

    • Each NamedArg shall be accessible by the caller. [ERROR]

    • If NumNamed = 0, then there shall be no further items in the CustomAttrib. [ERROR]

  7. The following rules apply to the structure of FixedArg (see Partition II, section 22.3):

    • If this item is not for a vector (a single-dimension array with lower bound of 0), then there shall be exactly one Elem. [ERROR]

    • If this item is for a vector, then:

      • NumElem shall be 1 or more. [ERROR]

      • This shall be followed by NumElem occurrences of Elem. [ERROR]

  8. The following rules apply to the structure of Elem (see Partition II, section 22.3):

    • If this is a simple type or an enum (see Partition II, section 22.3 for how this is defined), then Elem consists simply of its value. [ERROR]

    • If this is a string, or a Type, then Elem consists of a SerString a PackedLen count of bytes, followed by the UTF8 characters. [ERROR]

    • If this is a boxed simple value type (bool, char, float32, float64, int8, int16, int32, int64, unsigned int8, unsigned int16, unsigned int32 or unsigned int64), then Elem consists of the corresponding type denoter (ELEMENT_TYPE_BOOLEAN, ELEMENT_TYPE_CHAR, ELEMENT_TYPE_I1, ELEMENT_TYPE_U1, ELEMENT_TYPE_I2, ELEMENT_TYPE_U2, ELEMENT_TYPE_I4, ELEMENT_TYPE_U4, ELEMENT_TYPE_I8, ELEMENT_TYPE_U8, ELEMENT_TYPE_R4, ELEMENT_TYPE_R8), followed by its value. [ERROR]

  9. The following rules apply to the structure of NamedArg (see Partition II, section 22.3):

    • The single-byte FIELD (0x53) or PROPERTY (0x54) [ERROR]

    • The type of the field or property one of ELEMENT_TYPE_BOOLEAN, ELEMENT_TYPE_CHAR, ELEMENT_TYPE_I1, ELEMENT_TYPE_U1, ELEMENT_TYPE_I2, ELEMENT_TYPE_U2, ELEMENT_TYPE_I4, ELEMENT_TYPE_U4, ELEMENT_TYPE_I8, ELEMENT_TYPE_U8, ELEMENT_TYPE_R4, ELEMENT_TYPE_R8, ELEMENT_TYPE_STRING, or the constant 0x50 (for an argument of type System.Type)

    • The name of the field or property, respectively, with the previous item, as a SerString a PackedLen count of bytes, followed by the UTF8 characters of the name [ERROR]

    • A FixedArg (see above) [ERROR]

End informative text


21.11 DeclSecurity: 0x0E

Security attributes, which derive from System.Security.Permissions.SecurityAttribute (see the .NET Framework Standard Library Annotated Reference), can be attached to a TypeDef, a Method, or an Assembly. All constructors of this class shall take a System.Security.Permissions.SecurityAction value as their first parameter, describing what should be done with the permission on the type, method, or assembly to which it is attached. Code access security attributes, which derive from System.Security.Permissions.CodeAccessSecurityAttribute, may have any of the security actions.

These different security actions are encoded in the DeclSecurity table as a 2-byte enum (see below). All security custom attributes for a given security action on a method, type, or assembly shall be gathered together and one System.Security.PermissionSet instance shall be created, stored in the Blob heap, and referenced from the DeclSecurity table.

NOTE

The general flow from a compiler's point of view is as follows. The user specifies a custom attribute through some language-specific syntax that encodes a call to the attribute's constructor. If the attribute's type is derived (directly or indirectly) from System.Security.Permissions.SecurityAttribute, then it is a security custom attribute and requires special treatment, as follows (other custom attributes are handled by simply recording the constructor in the metadata as described in Partition II, section 21.10). The attribute object is constructed, and provides a method (CreatePermission) to convert it into a security permission object (an object derived from System.Security.Permission). All the permission objects attached to a given metadata item with the same security action are combined together into a System.Security.PermissionSet. This permission set is converted into a form that is ready to be stored in XML using its ToXML method to create a System.Security.SecurityElement. Finally, the XML that is required for the metadata is created using the ToString method on the security element.


The DeclSecurity table has the following columns:

  • Action (2-byte value)

  • Parent (index into the TypeDef, MethodDef, or Assembly table; more precisely, a HasDeclSecurity coded index)

  • PermissionSet (index into Blob heap)

Action is a 2-byte representation of security actions, see System.Security.SecurityAction in the .NET Framework Standard Library Annotated Reference. The values 0 through 0xFF are reserved for future standards use. Values 0x20 through 0x7F, and 0x100 through 0x07FF, are for uses where the action may be ignored if it is not understood or supported. Values 0x80 through 0xFF, and 0x0800 through 0xFFFF, are for uses where the action shall be implemented for secure operation; in implementations where the action is not available, no access to the assembly, type, or method shall be permitted.

Security Action

Note

Explanation of Behavior

Legal Scope

Assert

1

Without further checks, satisfy Demand for specified permission.

Method, Type

Demand

1

Check [that] all callers in the call chain have been granted specified permission, throw SecurityException (see the .NET Framework Standard Library Annotated Reference) on failure.

Method, Type

Deny

1

Without further checks, refuse Demand for specified permission.

Method, Type

InheritanceDemand

1

Specified permission shall be granted in order to inherit from class or override virtual method.

Method, Type

LinkDemand

1

Check [that] immediate caller has been granted specified permission, throw SecurityException (see the .NET Framework Standard Library Annotated Reference) on failure.

Method, Type

PermitOnly

1

Without further checks, refuse Demand for all permissions other than those specified.

Method, Type

RequestMinimum

 

Specify minimum permissions required to run.

Assembly

RequestOptional

 

Specify optional permissions to grant.

Assembly

RequestRefuse

 

Specify permissions not to be granted.

Assembly

NonCasDemand

2

Check that current assembly has been granted specified permission, throw SecurityException (see the .NET Framework Standard Library Annotated Reference otherwise).

Method, Type

NonCasLinkDemand

2

Check that immediate caller has been granted specified permission, throw SecurityException (see the .NET Framework Standard Library Annotated Reference) otherwise.

Method, Type

PrejitGrant

 

Reserved for implementation-specific use.

Assembly

Note 1: Specified attribute shall derive from System.Security.Permissions.CodeAccess-SecurityAttribute.

Note 2: Attribute shall derive from System.Security.Permissions.SecurityAttribute, but shall not derive from System.Security.Permissions.CodeAccessSecurityAttribute.

Parent is a metadata token that identifies the Method, Type, or Assembly on which security custom attributes serialized in PermissionSet were defined.

PermissionSet is a "blob" that contains the XML serialization of a permission set. The permission set contains the permissions that were requested with an Action on a specific Method, Type, or Assembly (see Parent).

The rows of the DeclSecurity table are filled by attaching a .permission or .permissionset directive that specifies the Action and PermissionSet on a parent assembly (see Partition II, section 6.6) or parent type or method (see Partition II, section 9.2).

This contains informative text only.


  1. Action may have only those values set that are specified. [ERROR]

  2. Parent shall be one of TypeDef, MethodDef, or Assembly. That is, it shall index a valid row in the TypeDef table, the MethodDef table, or the Assembly table. [ERROR]

  3. If Parent indexes a row in the TypeDef table, that row should not define an Interface. The security system ignores any such parent; compilers should not emit such permissions sets. [WARNING]

  4. If Parent indexes a TypeDef, then its TypeDef.Flags.HasSecurity bit should be set. [ERROR]

  5. If Parent indexes a MethodDef, then its MethodDef.Flags.HasSecurity bit should be set, [ERROR]

  6. PermissionSet should index a "blob" in the Blob heap. [ERROR]

  7. The format of the "blob" indexed by PermissionSet should represent a valid, serialized CLI object graph. The serialized form of all standardized permissions is specified in the .NET Framework Standard Library Annotated Reference. [ERROR]

End informative text


21.12 EventMap: 0x12

The EventMap table has the following columns:

  • Parent (index into the TypeDef table)

  • EventList (index into Event table). It marks the first of a contiguous run of Events owned by this Type. The run continues to the smaller of:

    • The last row of the Event table

    • The next run of Events, found by inspecting the EventList of the next row in the EventMap table

Note that EventMap info does not directly influence runtime behavior; what counts is the info stored for each method that the event comprises.

This contains informative text only.


  1. The EventMap table may contain zero or more rows.

  2. There shall be no duplicate rows, based upon Parent (a given class has only one "pointer" to the start of its event list). [ERROR]

  3. There shall be no duplicate rows, based upon EventList (different classes cannot share rows in the Event table). [ERROR]

End informative text


21.13 Event: 0x14

Events are treated within metadata much like Properties a way to associate a collection of methods defined on given class. There are two required methods add_ and remove_ plus optional raise_ and others. All of the methods gathered together as an Event shall be defined on the class.

The association between a row in the TypeDef table and the collection of methods that make up a given Event is held in three separate tables (exactly analogous to that used for Properties) see the [diagram] below:

graphics/05inf04.gif

Row 3 of the EventMap table indexes row 2 of the TypeDef table on the left (MyClass), while indexing row 4 of the Event table on the right the row for an Event called DocChanged. This setup establishes that MyClass has an Event called DocChanged. But what methods in the MethodDef table are gathered together as "belonging" to event DocChanged? That association is contained in the MethodSemantics table its row 2 indexes event DocChanged to the right, and row 2 in the MethodDef table to the left (a method called add_DocChanged). Also, row 3 of the MethodSemantics table indexes DocChanged to the right, and row 3 in the MethodDef table to the left (a method called remove_DocChanged). As the shading suggests, MyClass has another event, called TimedOut, with two methods, add_TimedOut and remove_TimedOut.

Event tables do a little more than group together existing rows from other tables. The Event table has columns for EventFlags, Name (e.g., DocChanged and TimedOut in the example here) and EventType. In addition, the MethodSemantics table has a column to record whether the method it points at is an add_, a remove_, a raise_, or other.

The Event table has the following columns:

  • EventFlags (a 2-byte bitmask of type EventAttribute; see Partition II, section 22.1.4)

  • Name (index into String heap)

  • EventType (index into TypeDef, TypeRef, or TypeSpec tables; more precisely, a TypeDefOrRef coded index) (this corresponds to the Type of the Event; it is not the Type that owns this event)

Note that Event information does not directly influence runtime behavior; what counts is the information stored for each method that the event comprises.

The EventMap and Event tables result from putting the .event directive on a class (see Partition II, section 17).

This contains informative text only.


  1. The Event table may contain zero or more rows.

  2. Each row shall have one, and only one, owner row in the EventMap table. [ERROR]

  3. EventFlags may have only those values set that are specified (all combinations valid). [ERROR]

  4. Name shall index a non-null string in the String heap. [ERROR]

    ANNOTATION

    Implementation-Specific (Microsoft): This string is limited to MAX_CLASS_NAME.


  5. The Name string shall be a valid CLS identifier. [CLS]

  6. EventType may be null or non-null.

  7. If EventType is non-null, then it shall index a valid row in the TypeDef or TypeRef table. [ERROR]

  8. If EventType is non-null, then the row in TypeDef, TypeRef, or TypeSpec table that it indexes shall be a Class (not an Interface; not a ValueType). [ERROR]

  9. For each row, there shall be one add_ and one remove_ row in the MethodSemantics table. [ERROR]

  10. For each row, there can be zero or one raise_ row, as well as zero or more other rows in the MethodSemantics table. [ERROR]

  11. Within the rows owned by a given row in the TypeDef table, there shall be no duplicates based upon Name. [ERROR]

  12. There shall be no duplicate rows based upon Name, where Name fields are compared using CLS conflicting-identifier-rules. [CLS]

End informative text


21.14 ExportedType: 0x27

The ExportedType table holds a row for each type, defined within other modules of this Assembly, that is exported out of this Assembly. In essence, it stores TypeDef row numbers of all types that are marked public in other modules that this Assembly comprises.

The actual target row in a TypeDef table is given by the combination of TypeDefId (in effect, row number) and Implementation (in effect, the module that holds the target TypeDef table). Note that this is the only occurrence in metadata of foreign tokens that is, token values that have a meaning in another module. (Regular token values are indices into the table in the current module.)

The full name of the type need not be stored directly. Instead, it may be split into two parts at any included "." (although typically this is done at the last "." in the full name). The part preceding the "." is stored as the TypeNamespace, and that following the "." is stored as the TypeName. If there is no "." in the full name, then the TypeNamespace shall be the index of the empty string.

The ExportedType table has the following columns:

  • Flags (a 4-byte bitmask of type TypeAttributes; see Partition II, section 22.1.14).

  • TypeDefId (4-byte index into a TypeDef table of another module in this Assembly). This field is used as a hint only. If the entry in the target TypeDef table matches the TypeName and TypeNamespace entries in this table, resolution has succeeded. But if there is a mismatch, the CLI shall fall back to a search of the target TypeDef table.

  • TypeName (index into the String heap).

  • TypeNamespace (index into the String heap).

  • Implementation. This can be an index (more precisely, an Implementation coded index) into one of two tables, as follows:

    • File table, where that entry says which module in the current assembly holds the TypeDef

    • ExportedType table, where that entry is the enclosing Type of the current nested Type

The rows in the ExportedType table are the result of the .class extern directive (see Partition II, section 6.7).

This contains informative text only.


The term "FullName" refers to the string created as follows: if the TypeNamespace is null, then use the TypeName; otherwise use the concatenation of Typenamespace, ".", and TypeName.

  1. The ExportedType table may contain zero or more rows.

  2. There shall be no entries in the ExportedType table for Types that are defined in the current module just for Types defined in other modules within the Assembly. [ERROR]

  3. Flags may have only those values set that are specified. [ERROR]

  4. If Implementation indexes the File table, then Flags.VisibilityMask shall be Public (see Partition II, section 22.1.14). [ERROR]

  5. If Implementation indexes the ExportedType table, then Flags.VisibilityMask shall be NestedPublic (see Partition II, section 22.1.14). [ERROR]

  6. If non-null, TypeDefId should index a valid row in a TypeDef table in a module somewhere within this Assembly (but not this module), and the row so indexed should have its Flags.Public = 1 (see Partition II, section 22.1.14). [WARNING]

  7. TypeName shall index a non-null string in the String heap. [ERROR]

    ANNOTATION

    Implementation-Specific (Microsoft): This string is limited to MAX_CLASS_NAME.


  8. TypeNamespace may be null or non-null.

  9. If TypeNamespace is non-null, then it shall index a non-null string in the String heap. [ERROR]

    ANNOTATION

    Implementation-Specific (Microsoft): This string is limited to MAX_CLASS_NAME. Also, the FullName (concatenated TypeNamespace+"."+TypeName) shall be less than MAX_CLASS_NAME.


  10. FullName shall be a valid CLS identifier. [CLS]

  11. If this is a nested Type, then TypeNamespace should be null, and TypeName should represent the unmangled, simple name of the nested Type. [ERROR]

  12. Implementation shall be a valid index into either: [ERROR]

    • The File table; that file shall hold a definition of the target Type in its TypeDef table.

    • A different row in the current ExportedType table this identifies the enclosing Type of the current, nested Type.

  13. FullName shall match exactly the corresponding FullName for the row in the TypeDef table indexed by TypeDefId. [ERROR]

  14. Ignoring nested Types, there shall be no duplicate rows, based upon FullName. [ERROR]

  15. For nested Types, there shall be no duplicate rows, based upon TypeName and enclosing Type. [ERROR]

  16. The complete list of Types exported from the current Assembly is given as the catenation of the ExportedType table with all public Types in the current TypeDef table, where "public" means a Flags.tdVisibilityMask of either Public or NestedPublic. There shall be no duplicate rows, in this concatenated table, based upon FullName (add Enclosing Type into the duplicates check if this is a nested Type). [ERROR]

End informative text


21.15 Field: 0x04

The Field table has the following columns:

  • Flags (a 2-byte bitmask of type FieldAttributes; see Partition II, section 22.1.5)

  • Name (index into String heap)

  • Signature (index into Blob heap)

Conceptually, each row in the Field table is owned by one, and only one, row in the TypeDef table. However, the owner of any row in the Field table is not stored anywhere in the Field table itself. There is merely a "forward-pointer" from each row in the TypeDef table (the FieldList column), as shown in the following illustration:

graphics/05inf05.gif

The TypeDef table has rows 1 through 4. The first row in the TypeDef table corresponds to a pseudo type, inserted automatically by the CLI. It is used to denote those rows in the Field table corresponding to global variables. The Field table has rows 1 through 6. Type 1 (pseudo type for "module") owns rows 1 and 2 in the Field table. Type 2 owns no rows in the Field table, even though its FieldList indexes row 3 in the Field table. Type 3 owns rows 3 through 5 in the Field table. Type 4 owns row 6 in the Field table. (The next pointers in the diagram show the next free row in each table) So, in the Field table, rows 1 and 2 belong to Type 1 (global variables); rows 3 through 5 belong to Type 3; row 6 belongs to Type 4.

Each row in the Field table results from a toplevel .field directive (see Partition II, section 5.10), or a .field directive inside a Type (see Partition II, section 9.2). For an example, see Partition II, section 13.5.

This contains informative text only.


  1. The Field table may contain zero or more rows.

  2. Each row shall have one, and only one, owner row in the TypeDef table. [ERROR]

  3. The owner row in the TypeDef table shall not be an Interface. [CLS]

  4. Flags may have only those set that are specified. [ERROR]

  5. The FieldAccessMask subfield of Flags shall contain precisely one of CompilerControlled, Private, FamANDAssem, Assembly, Family, FamORAssem, or Public (see Partition II, section 22.1.5). [ERROR]

  6. Flags may set 0 or 1 of Literal or InitOnly (not both) (see Partition II, section 22.1.5). [ERROR]

  7. If Flags.Literal = 1, then Flags.Static shall be 1 too (see Partition II, section 22.1.5). [ERROR]

  8. If Flags.RTSpecialName = 1, then Flags.SpecialName shall also be 1 (see Partition II, section 22.1.5). [ERROR]

  9. If Flags.HasFieldMarshal = 1, then this row shall "own" exactly one row in the FieldMarshal table (see Partition II, section 22.1.5). [ERROR]

  10. If Flags.HasDefault = 1, then this row shall "own" exactly one row in the Constant table (see Partition II, section 22.1.5). [ERROR]

  11. If Flags.HasFieldRVA = 1, then this row shall "own" exactly one row in the Field's RVA table (see Partition II, section 22.1.5). [ERROR]

  12. Name shall index a non-null string in the String heap. [ERROR]

    ANNOTATION

    Implementation-Specific (Microsoft): This string is limited to MAX_CLASS_NAME.


  13. The Name string shall be a valid CLS identifier. [CLS]

  14. Signature shall index a valid field signature in the Blob heap, [ERROR]

  15. If Flags.CompilerControlled = 1 (see Partition II, section 22.1.5), then this row is ignored completely in duplicate checking.

  16. If the owner of this field is the internally generated type called <Module>, it denotes that this field is defined at module scope (commonly called a global variable). In this case:

    • Flags.Static shall be 1. [ERROR]

    • The Flags.MemberAccessMask subfield shall be one of Public, CompilerControlled, or Private (see Partition II, section 22.1.5). [ERROR]

    • Module-scope fields are not allowed. [CLS]

  17. There shall be no duplicate rows in the Field table, based upon owner+Name+Signature (where owner is the owning row in the TypeDef table, as described above). (Note, however, that if Flags.CompilerControlled = 1, then this row is completely excluded from duplicate checking.) [ERROR]

  18. There shall be no duplicate rows in the Field table, based upon owner+Name, where Name fields are compared using CLS conflicting-identifier-rules. So, for example, "int i" and "float i" would be considered CLS duplicates. (Note, however, that if Flags.CompilerControlled = 1, then this row is completely excluded from duplicate checking, as noted above.) [CLS]

  19. If this is a field of an Enum, and Name string = "value__", then:

    1. RTSpecialName shall be 1. [ERROR]

    2. The owner row in the TypeDef table shall derive directly from System.Enum. [ERROR]

    3. The owner row in the TypeDef table shall have no other instance fields. [CLS]

    4. Its Signature shall be one of (see Partition II, section 22.1.15): [CLS]

      • ELEMENT_TYPE_U1

      • ELEMENT_TYPE_I2

      • ELEMENT_TYPE_I4

      • ELEMENT_TYPE_I8

  20. Its Signature shall be an integral type.

End informative text


21.16 FieldLayout: 0x10

The FieldLayout table has the following columns:

  • Offset (a 4-byte constant)

  • Field (index into the Field table)

Note that each Field in any Type is defined by its Signature. When a Type instance (ie, an object) is laid out by the CLI, each Field is one of four kinds:

  • Scalar for any member of built-in, such as int32. The size of the field is given by the size of that intrinsic, which varies between 1 and 8 bytes.

  • ObjectRef for CLASS, STRING, OBJECT, ARRAY, SZARRAY.

  • Pointer for PTR, FNPTR.

  • ValueType for VALUETYPE. The instance of that ValueType is actually laid out in this object, so the size of the field is the size of that ValueType.

(The list above uses an abbreviation each all-caps name should be prefixed by ELEMENT_TYPE_; so, for example, STRING is actually ELEMENT_TYPE_STRING. See Partition II, section 22.1.15.)

Note that metadata specifying explicit structure layout may be valid for use on one platform but not another, since some of the rules specified here are dependent on platform-specific alignment rules.

A row in the FieldLayout table is created if the .field directive for the parent field has specified a field offset (see Partition II, section 9.7).

This contains informative text only.


  1. A FieldLayout table may contain zero or more or rows.

  2. The Type whose Fields are described by each row of the FieldLayout table shall have Flags.ExplicitLayout (see Partition II, section 22.1.14) set. [ERROR]

  3. Offset shall be zero or more (cannot be negative). [ERROR]

  4. Field shall index a valid row in the Field table. [ERROR]

  5. The row in the Field table indexed by Field shall be non-static (i.e., its Flags.Static shall be 0). [ERROR]

  6. Among the rows owned by a given Type, there shall be no duplicates, based upon Field. That is, a given Field of a Type cannot be given two offsets. [ERROR]

  7. Each Field of kind ObjectRef shall be naturally aligned within the Type. [ERROR]

  8. No Field of kind ObjectRef may overlap any other Field no matter what its kind, wholly or partially. [ERROR]

  9. Among the rows owned by a given Type, it is perfectly legal for several rows to have the same value of Offset, so long as they are not of type ObjectRef (used to define C unions, for example). [ERROR]

  10. If ClassSize in the owner ClassLayout row is non-zero, then no Field may extend beyond that ClassSize (i.e., the Field Offset value plus the Field's calculated size shall not exceed ClassSize) (note that it is legal, and common, for ClassSize to be supplied as larger than the calculated object size the CLI pads the object with trailing bytes up to the ClassSize value.) [ERROR]

  11. Every Field of an ExplicitLayout Type shall be given an offset that is, it shall have a row in the FieldLayout table. [ERROR]

ANNOTATION

Implementation-Specific (Microsoft): Note that the rules above specify what is legal, or non-legal, metadata. However, there is a finer distinction that can be drawn what layouts permit typesafe access by code? For example, a class that overlaps two ValueTypes constitutes legal metadata, but accesses to that class may result in code that is not provably typesafe. At runtime, it is the Class loader that will perform these type-safety checks. Version 1 takes a simple approach if the type has any explicit layout, it is not typesafe. (This may be refined in future versions.)


End informative text


21.17 FieldMarshal: 0x0D

The FieldMarshal table has two columns. It "links" an existing row in the Field or Param table to information in the Blob heap that defines how that field or parameter (which, as usual, covers the method return, as parameter number 0) should be marshalled when calling to or from unmanaged code via PInvoke dispatch.

Note that FieldMarshal information is used only by code paths that arbitrate operation with unmanaged code. In order to execute such paths, the caller, on most platforms, would be installed with elevated security permission. Once it invokes unmanaged code, it lies outside the regime that the CLI can check it is simply trusted not to violate the type system.

The FieldMarshal table has the following columns:

  • Parent (index into Field or Param table; more precisely, a HasFieldMarshal coded index)

  • NativeType (index into the Blob heap)

For the detailed format of the "blob," see Partition II, section 22.4.

A row in the FieldMarshal table is created if the .field directive for the parent field has specified a .marshal attribute (see Partition II, section 15.1).

This contains informative text only.


  1. A FieldMarshal table may contain zero or more rows.

  2. Parent shall index a valid row in the Field or Param table (Parent values are encoded to say which of these two tables each refers to). [ERROR]

  3. NativeType shall index a non-null "blob" in the Blob heap. [ERROR]

  4. No two rows can point to the same parent. In other words, after the Parent values have been decoded to determine whether they refer to the Field or the Param table, no two rows can point to the same row in the Field table or in the Param table. [ERROR]

  5. The following checks apply to the MarshalSpec "blob" (see Partition II, section 22.4):

    1. NativeIntrinsic shall be exactly one of the constant values in its production. [ERROR]

    2. If NativeIntrinsic has the value BYVALSTR, then Parent shall point to a row in the Field table, not the Param table. [ERROR]

    3. If FIXEDARRAY, then Parent shall point to a row in the Field table, not the Param table. [ERROR]

    4. If FIXEDARRAY, then NumElem shall be 1 or more. [ERROR]

    5. If FIXEDARRAY, then ArrayElemType shall be exactly one of the constant values in its production. [ERROR]

    6. If ARRAY, then ArrayElemType shall be exactly one of the constant values in its production. [ERROR]

    7. If ARRAY, then ParamNum may be zero.

    8. If ARRAY, then ParamNum cannot be < 0. [ERROR]

    9. If ARRAY and ParamNum > 0, then Parent shall point to a row in the Param table, not in the Field table. [ERROR]

    10. If ARRAY and ParamNum > 0, then ParamNum cannot exceed the number of parameters supplied to the MethodDef (or MethodRef if a VARARG call) of which the parent Param is a member. [ERROR]

    11. If ARRAY, then ElemMult shall be >= 1. [ERROR]

    12. If ARRAY and ElemMult <> 1 issue a warning, because it is probably a mistake [WARNING]

    13. If ARRAY and ParamNum == 0, then NumElem shall be >= 1. [ERROR]

    14. If ARRAY and ParamNum != 0 and NumElem != 0, then issue a warning because it is probably a mistake. [WARNING]

ANNOTATION

Implementation-Specific (Microsoft): The following rules apply to Microsoft-specific features:

  1. If CUSTOMMARSHALLER, then Guid shall be an in-place, counted-UTF8 string that represents a string-format GUID. Its length, when expanded from UTF8, shall be exactly 38 characters, to include leading ( and trailing ). [ERROR]

  2. If CUSTOMMARSHALLER, then UnmanagedType shall be a non-empty, counted-UTF8 string. [ERROR]

  3. If CUSTOMMARSHALLER, then ManagedType shall be a non-empty, counted-UTF8 string that represents the fully qualified Namespace+"."+Name of a Class or ValueType defined somewhere within the current Assembly. [ERROR]

  4. If CUSTOMMARSHALLER, then Cookie shall be a counted-UTF8 string its size may legally be zero. [ERROR]

  5. If SAFEARRAY, then SafeArrayElemType shall be exactly one of the constant values in its production. [ERROR]


End informative text


21.18 FieldRVA: 0x1D

The FieldRVA table has the following columns:

  • RVA (a 4-byte constant)

  • Field (index into Field table)

Conceptually, each row in the FieldRVA table is an extension to exactly one row in the Field table, and records the RVA (Relative Virtual Address) within the image file at which this field's initial value is stored.

A row in the FieldRVA table is created for each static parent field that has specified the optional data label (see Partition II, section 15). The RVA column is the Relative Virtual Address of the data in the PE file (see Partition II, section 15.3).

This contains informative text only.


  1. RVA shall be non-zero. [ERROR]

  2. RVA shall point into the current module's data area (not its metadata area). [ERROR]

  3. Field shall index a valid table in the Field table. [ERROR]

  4. Any field with an RVA shall be a ValueType (not a Class, and not an Interface). Moreover, it shall not have any private fields (and likewise for any of its fields that are themselves ValueTypes). (If any of these conditions were breached, code could overlay that global static and access its private fields.) Moreover, no fields of that ValueType can be Object References (into the GC heap). [ERROR]

  5. So long as two RVA-based fields comply with the previous conditions, the ranges of memory spanned by the two ValueTypes may overlap, with no further constraints. This is not actually an additional rule; it simply clarifies the position with regard to overlapped RVA-based fields.

End informative text


21.19 File: 0x26

The File table has the following columns:

  • Flags (a 4-byte bitmask of type FileAttributes; see Partition II, section 22.1.6)

  • Name (index into String heap)

  • HashValue (index into Blob heap)

The rows of the File table result from .file directives in an Assembly (see Partition II, section 6.2.3).

This contains informative text only.


  1. Flags may have only those values set that are specified (all combinations valid). [ERROR]

  2. Name shall index a non-null string in the String heap. It shall be in the format <filename>.<extension> (e.g., "foo.dll", but not "c:\Utils\foo.dll"). [ERROR]

    ANNOTATION

    Implementation-Specific (Microsoft): This string is limited to MAX_PATH_NAME.

    Also, the following values for Name are illegal (these represent device, rather than file, names):

    S [N] [[C]*]

    where

    S ::= con | aux | lpt | prn | null | com (case-blind)

    N ::= a number 0 .. 9

    C ::= $ | :

    "[]" denotes optional, "*" denotes Kleene closure, "|" denotes alternatives. [ERROR]

    The CLI also checks dynamically against opening a device, which can be assigned an arbitrary name by the user.


  3. HashValue shall index a non-empty "blob" in the Blob heap. [ERROR]

  4. There shall be no duplicate rows rows with the same Name value. [ERROR]

  5. If this module contains a row in the Assembly table (that is, if this module "holds the manifest"), then there shall not be any row in the File table for this module i.e., no self-reference. [ERROR]

  6. If the File table is empty, then this, by definition, is a single-file assembly. In this case, the ExportedType table should be empty. [WARNING]

End informative text


21.20 ImplMap: 0x1C

The ImplMap table holds information about unmanaged methods that can be reached from managed code, using PInvoke dispatch.

Each row of the ImplMap table associates a row in the MethodDef table (MemberForwarded) with the name of a routine (ImportName) in some unmanaged DLL (ImportScope).

NOTE

A typical example would be: associate the managed Method stored in row N of the Method table (so MemberForwarded would have the value N) with the routine called "GetEnvironmentVariable" (the string indexed by ImportName) in the DLL called "kernel32" (the string in the ModuleRef table indexed by ImportScope). The CLI intercepts calls to managed Method number N, and instead forwards them as calls to the unmanaged routine called "GetEnvironmentVariable" in "kernel32.dll" (including marshalling any arguments, as required).

The CLI does not support this mechanism to access fields that are exported from a DLL only methods.


The ImplMap table has the following columns:

  • MappingFlags (a 2-byte bitmask of type PInvokeAttributes; see Partition II, section 22.1.7)

  • MemberForwarded (index into the Field or MethodDef table; more precisely, a MemberForwarded coded index. However, it only ever indexes the MethodDef table, since Field export is not supported.

  • ImportName (index into the String heap)

  • ImportScope (index into the ModuleRef table)

A row is entered in the ImplMap table for each parent Method (see Partition II, section 14.5) that is defined with a .pinvokeimpl interoperation attribute specifying the MappingFlags, ImportName, and ImportScope. For an example see Partition II, section 14.5.

This contains informative text only.


  1. ImplMap may contain zero or more rows.

  2. MappingFlags may have only those values set that are specified. [ERROR]

  3. MemberForwarded shall index a valid row in the MethodDef table. [ERROR]

  4. The MappingFlags.CharSetMask (see Partition II, section 22.1.7) in the row of the MethodDef table indexed by MemberForwarded shall have at most one of the following bits set: CharSetAnsi, CharSetUnicode, or CharSetAuto (if none set, the default is CharSetNotSpec). [ERROR]

    ANNOTATION

    Implementation-Specific (Microsoft): The MappingFlags.CallConvMask in the row of the Method table indexed by MemberForwarded may have at most one of the following values: CallConvWinapi, CallConvCdecl, CallConvStdcall. It cannot have the value CallConvFastcall or CallConvThiscall. [ERROR]


  5. ImportName shall index a non-null string in the String heap. [ERROR]

    ANNOTATION

    Implementation-Specific (Microsoft): This string is limited to MAX_CLASS_NAME.


  6. ImportScope shall index a valid row in the ModuleRef table. [ERROR]

  7. The row indexed in the MethodDef table by MemberForwarded shall have its Flags.PinvokeImpl = 1, and Flags.Static = 1. [ERROR]

End informative text


21.21 InterfaceImpl: 0x09

The InterfaceImpl table has the following columns:

  • Class (index into the TypeDef table)

  • Interface (index into the TypeDef, TypeRef, or TypeSpec table; more precisely, a TypeDefOrRef coded index)

The InterfaceImpl table records which interfaces a Type implements. Conceptually, each row in the InterfaceImpl table says that Class implements Interface.

This contains informative text only.


  1. The InterfaceImpl table may contain zero or more rows.

  2. Class shall be non-null. [ERROR]

    ANNOTATION

    Implementation-Specific (Microsoft): If Class = null, this row should be treated as if it did not exist. Used to mark a class deleted, in incremental compilation scenarios, without physically deleting its metadata.


  3. If Class is non-null, then:

    • Class shall index a valid row in the TypeDef table. [ERROR]

    • Interface shall index a valid row in the TypeDef or TypeRef table. [ERROR]

    • The row in the TypeDef, TypeRef, or TypeSpec table indexed by Interface shall be an Interface (Flags.Interface = 1), not a Class or ValueType. [ERROR]

  4. There should be no duplicates in the InterfaceImpl table, based upon non-null Class and Interface values. [WARNING]

  5. There can be many rows with the same value for Class (a class can implement many interfaces).

  6. There can be many rows with the same value for Interface (many classes can implement the same interface).

End informative text


21.22 ManifestResource: 0x28

The ManifestResource table has the following columns:

  • Offset (a 4-byte constant)

  • Flags (a 4-byte bitmask of type ManifestResourceAttributes; see Partition II, section 22.1.8)

  • Name (index into the String heap)

  • Implementation (index into File table, or AssemblyRef table, or null; more precisely, an Implementation coded index)

The Offset specifies the byte offset within the referenced file at which this resource record begins. The Implementation specifies which file holds this resource. The rows in the table result from .mresource directives on the Assembly (see Partition II, section 6.2.2).

This contains informative text only.


  1. The ManifestResource table may contain zero or more rows.

  2. Offset shall be a valid offset into the target file, starting from the Resource entry in the COR header. [ERROR]

  3. Flags may have only those values set that are specified. [ERROR]

  4. The VisibilityMask (see Partition II, section 22.1.8) subfield of Flags shall be one of Public or Private. [ERROR]

  5. Name shall index a non-null string in the String heap. [ERROR]

    ANNOTATION

    Implementation-Specific (Microsoft): This string is limited to MAX_CLASS_NAME.


  6. Implementation may be null or non-null (if null, it means the resource is stored in the current file).

  7. If Implementation is null, then Offset shall be a valid offset in the current file, starting from the Resource entry in the CLI header. [ERROR]

  8. If Implementation is non-null, then it shall index a valid row in the File or AssemblyRef table. [ERROR]

  9. There shall be no duplicate rows, based upon Name. [ERROR]

  10. If the resource is an index into the File table, Offset shall be zero. [ERROR]

End informative text


21.23 MemberRef: 0x0A

The MemberRef table combines two sorts of references to Fields and to Methods of a class, known as "MethodRef" and "FieldRef", respectively. The MemberRef table has the following columns:

  • Class (index into the TypeRef, ModuleRef, MethodDef, TypeSpec, or TypeDef tables; more precisely, a MemberRefParent coded index)

  • Name (index into String heap)

  • Signature (index into Blob heap)

An entry is made into the MemberRef table whenever a reference is made, in the CIL code, to a method or field which is defined in another module or assembly. (Also, an entry is made for a call to a method with a VARARG signature, even when it is defined in the same module as the call site.)

This contains informative text only.


  1. Class shall be one of: [ERROR]

    1. A TypeRef token, if the class that defines the member is defined in another module. (Note: It is unusual, but legal, to use a TypeRef token when the member is defined in this same module its TypeDef token can be used instead.)

    2. A ModuleRef token, if the member is defined, in another module of the same assembly, as a global function or variable.

    3. A MethodDef token, when used to supply a call-site signature for a varargs method that is defined in this module. The Name shall match the Name in the corresponding MethodDef row. The Signature shall match the Signature in the target method definition. [ERROR]

    4. A TypeSpec token, if the member is a member of a constructed type.

  2. Class shall not be null (this would indicate an unresolved reference to a global function or variable). [ERROR]

  3. Name shall index a non-null string in the String heap. [ERROR]

    ANNOTATION

    Implementation-Specific (Microsoft): This string is limited to MAX_CLASS_NAME.


  4. The Name string shall be a valid CLS identifier. [CLS]

  5. Signature shall index a valid field or method signature in the Blob heap. In particular, it shall embed exactly one of the following "calling conventions": [ERROR]

    1. DEFAULT (0x0)

    2. VARARG (0x5)

    3. FIELD (0x6)

    ANNOTATION

    Implementation-Specific (Microsoft): The above names are defined in the file inc\CorHdr.h as part of the Microsoft .NET SDK, using the prefix IMAGE_CEE_ CS_CALLCONV_.


  6. The MemberRef table shall contain no duplicates, where duplicate rows have the same Class, Name, and Signature. [WARNING]

  7. Signature shall not have the VARARG (0x5) calling convention. [CLS]

  8. There shall be no duplicate rows, where Name fields are compared using CLS conflicting-identifier-rules. [CLS]

  9. There shall be no duplicate rows, where Name fields are compared using CLS conflicting-identifier-rules. (Note, in particular, that the return type, and whether parameters are marked ELEMENT_TYPE_BYREF (see Partition II, section 22.1.15) are ignored in the CLS. For example, int foo() and double foo() result in duplicate rows by CLS rules. Similarly, void bar(int i) and void bar(int& i) also result in duplicate rows by CLS rules.) [CLS]

    ANNOTATION

    Implementation-Specific (Microsoft): Name shall not be of the form _VtblGapSequenceNumber<_CountOfSlots> such methods are dummies, used to pad entries in the vtable that CLI generates for COM interop. Such methods cannot be called from managed or unmanaged code. [ERROR]


  10. If Class and Name resolve to a field, then that field shall not have a value of CompilerControlled (see Partition II, section 22.1.5) in its Flags.FieldAccessMask subfield. [ERROR]

  11. If Class and Name resolve to a method, then that method shall not have a value of CompilerControlled in its Flags.MemberAccessMask (see Partition II, section 22.1.9) subfield. [ERROR]

End informative text


21.24 MethodDef: 0x06

The MethodDef table has the following columns:

  • RVA (a 4-byte constant).

  • ImplFlags (a 2-byte bitmask of type MethodImplAttributes; see Partition II, section 22.1.10).

  • Flags (a 2-byte bitmask of type MethodAttributes; see Partition II, section 22.1.9).

  • Name (index into String heap).

  • Signature (index into Blob heap).

  • ParamList (index into Param table). It marks the first of a contiguous run of Parameters owned by this method. The run continues to the smaller of:

    • The last row of the Param table

    • The next run of Parameters, found by inspecting the ParamList of the next row in the MethodDef table

Conceptually, every row in the MethodDef table is owned by one, and only one, row in the TypeDef table.

The rows in the MethodDef table result from .method directives (see Partition II, section 14). The RVA column is computed when the image for the PE file is emitted and points to the Cor_ILMethod structure for the body of the method (see Partition II, section 24.4).

This contains informative text only.


  1. The MethodDef table may contain zero or more rows.

  2. Each row shall have one, and only one, owner row in the TypeDef table. [ERROR]

  3. ImplFlags may have only those values set that are specified. [ERROR]

  4. Flags may have only those values set that are specified. [ERROR]

  5. The MemberAccessMask (see Partition II, section 22.1.9) subfield of Flags shall contain precisely one of CompilerControlled, Private, FamANDAssem, Assem, Family, FamORAssem, or Public. [ERROR]

  6. The following combined bit settings in Flags are illegal: [ERROR]

    1. Static | Final

    2. Static | Virtual

    3. Static | NewSlot

    4. Final | Abstract

    5. Abstract | PinvokeImpl

    6. CompilerControlled | Virtual

    7. CompilerControlled | Final

    8. CompilerControlled | SpecialName

    9. CompilerControlled | RTSpecialName

  7. An abstract method shall be virtual. So: if Flags.Abstract = 1, then Flags.Virtual shall also be 1. [ERROR]

  8. If Flags.RTSpecialName = 1, then Flags.SpecialName shall also be 1. [ERROR]

    ANNOTATION

    Implementation-Specific (Microsoft): An abstract method cannot have ForwardRef (see Partition II, section 22.1.10) set, and vice versa. So:

    • If Flags.Abstract = 1, then ImplFlags.ForwardRef shall be 0. [ERROR]

    • If ImplFlags.ForwardRef = 1, then Flags.Abstract shall be 0. [ERROR]

    The ForwardRef bit may be set only in an OBJ file (used by managed extensions for C++). By the time a method executes, its ForwardRef shall be 0. [ERROR]


  9. If Flags.HasSecurity = 1, then at least one of the following conditions shall be true: [ERROR]

    • This Method owns at least [one] row in the DeclSecurity table.

    • This Method has a custom attribute called SuppressUnmanagedCodeSecurityAttribute.

  10. If this Method owns one (or more) rows in the DeclSecurity table, then Flags.HasSecurity shall be 1. [ERROR]

  11. If this Method has a custom attribute called SuppressUnmanagedCodeSecurityAttribute, then Flags.HasSecurity shall be 1. [ERROR]

  12. A Method may have a custom attribute called DynamicSecurityMethodAttribute but this has no effect whatsoever upon the value of its Flags.HasSecurity.

  13. Name shall index a non-null string in the String heap. [ERROR]

    ANNOTATION

    Implementation-Specific (Microsoft): This string is limited to MAX_CLASS_NAME.


  14. Interfaces cannot have instance constructors. So, if this Method is owned by an Interface, then its Name cannot be .ctor. [ERROR]

  15. Interfaces can only own virtual methods (not static or instance methods). So, if this Method is owned by an Interface, Flags.Static shall be clear. [ERROR]

  16. The Name string shall be a valid CLS identifier (unless Flags.RTSpecialName is set for example, .cctor is legal). [CLS]

  17. Signature shall index a valid method signature in the Blob heap. [ERROR]

  18. If Flags.CompilerControlled = 1, then this row is ignored completely in duplicate checking.

  19. If the owner of this method is the internally generated type called <Module>, it denotes that this method is defined at module scope. (In C++, the method is called "global" and can be referenced only within its compiland, from its point of declaration forward.) In this case:

    1. Flags.Static shall be 1. [ERROR]

    2. Flags.Abstract shall be 0. [ERROR]

    3. Flags.Virtual shall be 0. [ERROR]

    4. The Flags.MemberAccessMask subfield shall be one of CompilerControlled, Public, or Private. [ERROR]

    5. Module-scope methods are not allowed. [CLS]

  20. It makes no sense for ValueTypes, which have no identity, to have synchronized methods (unless they are boxed). So, if the owner of this method is a ValueType, then the method cannot be synchronized; i.e., ImplFlags.Synchronized shall be 0. [ERROR]

  21. There shall be no duplicate rows in the MethodDef table, based upon owner+Name+Signature (where owner is the owning row in the TypeDef table). (Note, however, that if Flags.CompilerControlled = 1, then this row is completely excluded from duplicate checking.) [ERROR]

  22. There shall be no duplicate rows in the MethodDef table, based upon owner+Name+Signature, where Name fields are compared using CLS conflicting-identifier-rules; also, the Type defined in the signatures shall be different. So, for example, "int i" and "float i" would be considered CLS duplicates; also, the return type of the method is ignored. (Note, however, that if Flags.CompilerControlled = 1, then this row is completely excluded from duplicate checking, as explained above.) [CLS]

  23. If Final or NewSlot is set in Flags, then Flags.Virtual shall also be set. [ERROR]

  24. If Flags.PInvokeImpl is set, then Flags.Virtual shall be 0. [ERROR]

  25. If Flags.Abstract != 1, then exactly one of the following shall also be true: [ERROR]

    • RVA != 0

    • Flags.PInvokeImpl = 1

    • ImplFlags.Runtime = 1

    ANNOTATION

    Implementation-Specific (Microsoft): There is an additional mutually exclusive possibility related to COM interop: the owner of this method is marked Import = 1.


  26. If the method is CompilerControlled, then the RVA shall be non-zero or marked with PinvokeImpl = 1. [ERROR]

  27. Signature shall have exactly one of the following managed calling conventions: [ERROR]

    1. DEFAULT (0x0)

    2. VARARG (x5)

    ANNOTATION

    Implementation-Specific (Microsoft): The above names are defined in the file inc\CorHdr.h as part of the Microsoft .NET SDK, using a prefix of IMAGE_CEE_ CS_CALLCONV_.


  28. Signature shall have the calling-convention DEFAULT (0x0). [CLS]

  29. Signature: If and only if the method is not Static, then the calling convention byte in Signature has its HASTHIS (0x20) bit set. [ERROR]

  30. Signature: If the method is Static, then the HASTHIS (0x20) bit in the calling convention byte shall be 0. [ERROR]

  31. If EXPLICITTHIS (0x40) in the signature is set, then HASTHIS (0x20) shall also be set (note in passing: if EXPLICITTHIS is set, then the code is not verifiable). [ERROR]

  32. The EXPLICITTHIS (0x40) bit can be set only in signatures for function pointers: signatures whose MethodDefSig is preceded by FNPTR (0x1B). [ERROR]

  33. If RVA = 0, then either: [ERROR]

    • Flags.Abstract = 1, or

    • ImplFlags.Runtime = 1, or

    • Flags.PinvokeImpl = 1

    ANNOTATION

    Implementation-Specific (Microsoft): There are two additional mutually exclusive possibilities:

    • ImplFlags.InternalCall = 1, or

    • The owner row in the TypeDef table has Flags.Import = 1


  34. If RVA != 0, then: [ERROR]

    1. Flags.Abstract shall be 0, and

    2. ImplFlags.CodeTypeMask shall be exactly one of the following values: Native, CIL, or Runtime, and

    3. RVA shall point into the CIL code stream in this file.

    ANNOTATION

    Implementation-Specific (Microsoft): There are two additional requirements:

    • ImplFlags.InternalCall = 0, and

    • The owner row in the TypeDef table has Flags.tdImport = 0


  35. If Flags.PinvokeImpl = 1, then: [ERROR]

    • RVA = 0 and the method owns a row in the ImplMap table, OR

    ANNOTATION

    Implementation-Specific (Microsoft): For IJW ("It Just Works") thunks there is an additional possibility, where the method is actually a managed method in the current module:

    RVA != 0 and the method does not own a row in the ImplMap table and the method signature includes a custom modifier that specifies the native calling convention.


  36. If Flags.RTSpecialName = 1, then Name shall be one of: [ERROR]

    1. .ctor (object constructor method)

    2. .cctor (class constructor method)

    ANNOTATION

    Implementation-Specific (Microsoft): For COM interop, an additional class of method names is permitted:

    _VtblGap<SequenceNumber>_<CountOfSlots>

    where <SequenceNumber> and <CountOfSlots> are decimal numbers.


  37. Conversely, if Name is any of the above special names, then Flags.RTSpecialName shall be set. [ERROR]

  38. If Name = .ctor (object constructor method), then:

    1. The return type in Signature shall be ELEMENT_TYPE_VOID (see Partition II, section 22.1.15). [ERROR]

    2. Flags.Static shall be 0. [ERROR]

    3. Flags.Abstract shall be 0. [ERROR]

    4. Flags.Virtual shall be 0. [ERROR]

    5. The "owner" type shall be a valid Class or ValueType (not <Module> and not an Interface) in the TypeDef table. [ERROR]

    6. There can be 0 or more .ctors for any given "owner."

  39. If Name = .cctor (class constructor method), then:

    1. The return type in Signature shall be ELEMENT_TYPE_VOID (see Partition II, section 22.1.15). [ERROR]

    2. Signature shall have DEFAULT (0x0) for its calling convention. [ERROR]

    3. There shall be no parameters supplied in Signature. [ERROR]

    4. Flags.Static shall be set. [ERROR]

    5. Flags.Virtual shall be clear. [ERROR]

    6. Flags.Abstract shall be clear. [ERROR]

  40. Among the set of methods owned by any given row in the TypeDef table, there can be zero or one method named .cctor (never two or more). [ERROR]

End informative text


21.25 MethodImpl: 0x19

MethodImpls let a compiler override the default inheritance rules provided by the CLI. Their original use was to allow a class "C" that inherited method "Foo" from interfaces I and J, to provide implementations for both methods (rather than have only one slot for "Foo" in its vtable). But MethodImpls can be used for other reasons too, limited only by the compiler writer's ingenuity within the constraints defined in the validation rules below.

In the example above, Class specifies "C", MethodDeclaration specifies I::Foo, and MethodBody specifies the method which provides the implementation for I::Foo (either a method body within "C", or a method body implemented by a superclass of "C").

The MethodImpl table has the following columns:

  • Class (index into TypeDef table)

  • MethodBody (index into MethodDef or MemberRef table; more precisely, a MethodDefOrRef coded index)

  • MethodDeclaration (index into MethodDef or MemberRef table; more precisely, a MethodDefOrRef coded index)

ilasm uses the .override directive to specify the rows of the MethodImpl table (see Partition II, section 9.3.2).

This contains informative text only.


  1. The MethodImpl table may contain zero or more rows.

  2. Class shall index a valid row in the TypeDef table. [ERROR]

  3. MethodBody shall index a valid row in the Method or MethodRef table. [ERROR]

  4. The method indexed by MethodDeclaration shall have Flags.Virtual set. [ERROR]

  5. The owner Type of the method indexed by MethodDeclaration shall not have Flags.Sealed = 0. [ERROR]

  6. The method indexed by MethodBody shall be a member of Class or some superclass of Class (MethodImpls do not allow compilers to "hook" arbitrary method bodies). [ERROR]

  7. The method indexed by MethodBody shall be virtual. [ERROR]

  8. The method indexed by MethodBody shall have its Method.RVA != 0 (cannot be an unmanaged method reached via PInvoke, for example). [ERROR]

  9. MethodDeclaration shall index a method in the ancestor chain of Class (reached via its Extends chain) or in the interface tree of Class (reached via its InterfaceImpl entries). [ERROR]

  10. The method indexed by MethodDeclaration shall not be final (its Flags.Final shall be 0). [ERROR]

  11. The method indexed by MethodDeclaration shall be accessible to Class. [ERROR]

  12. The method signature defined by MethodBody shall match those defined by MethodDeclaration. [ERROR]

  13. There shall be no duplicate rows, based upon Class+MethodDeclaration. [ERROR]

End informative text


21.26 MethodSemantics: 0x18

The MethodSemantics table has the following columns:

  • Semantics (a 2-byte bitmask of type MethodSemanticsAttributes; see Partition II, section 22.1.11)

  • Method (index into the MethodDef table)

  • Association (index into the Event or Property table; more precisely, a HasSemantics coded index)

The rows of the MethodSemantics table are filled by .property (see Partition II, section 16) and .event (see Partition II, section 17) directives. See Partition II, section 21.13 for more information.

This contains informative text only.


  1. The MethodSemantics table may contain zero or more rows.

  2. Semantics may have only those values set that are specified. [ERROR]

  3. Method shall index a valid row in the MethodDef table, and that row shall be for a method defined on the same class as the Property or Event this row describes. [ERROR]

  4. All methods for a given Property or Event shall have the same accessibility (i.e., the MemberAccessMask subfield of their Flags row) and cannot be CompilerControlled. [CLS]

  5. Semantics: constrained as follows:

    • If this row is for a Property, then exactly one of Setter, Getter, or Other shall be set. [ERROR]

    • If this row is for an Event, then exactly one of AddOn, RemoveOn, Fire, or Other shall be set. [ERROR]

  6. If this row is for an Event, and its Semantics is Addon or RemoveOn, then the row in the MethodDef table indexed by Method shall take a Delegate as a parameter, and return void. [ERROR]

  7. If this row is for an Event, and its Semantics is Fire, then the row indexed in the MethodDef table by Method may return any type.

    ANNOTATION

    Implementation-Specific (Microsoft): The Microsoft implementation limits the return type of the Fire method to void.


  8. For each property, there shall be a setter, or a getter, or both. [CLS]

  9. Any getter method for a property whose Name is xxx shall be called get_xxx. [CLS]

  10. Any setter method for a property whose Name is xxx shall be called set_xxx. [CLS]

  11. If a property provides both getter and setter methods, then these methods shall have the same value in the Flags.MemberAccessMask subfield. [CLS]

  12. If a property provides both getter and setter methods, then these methods shall have the same value for their Method.Flags.Virtual. [CLS]

  13. Any getter and setter methods shall have Method.Flags.SpecialName = 1. [CLS]

  14. Any getter method shall have a return type which matches the signature indexed by the Property.Type field. [CLS]

  15. The last parameter for any setter method shall have a type which matches the signature indexed by the Property.Type field. [CLS]

  16. Any setter method shall have return type ELEMENT_TYPE_VOID (see Partition II, section 22.1.15) in Method.Signature. [CLS]

  17. If the property is indexed, the indices for getter and setter shall agree in number and type. [CLS]

  18. Any AddOn method for an event whose Name is xxx shall have the signature: void add_xxx (<DelegateType> handler) [CLS]

  19. Any RemoveOn method for an event whose Name is xxx shall have the signature: void remove_xxx(<DelegateType> handler). [CLS]

  20. Any Fire method for an event whose Name is xxx shall have the signature: void raise_xxx(Event e). [CLS]

End informative text


21.27 Module: 0x00

The Module table has the following columns:

  • Generation (2-byte value, reserved, shall be zero)

  • Name (index into String heap)

  • Mvid (index into Guid heap; simply a GUID used to distinguish between two versions of the same module)

  • EncId (index into Guid heap, reserved, shall be zero)

  • EncBaseId (index into Guid heap, reserved, shall be zero)

The Mvid column shall index a unique GUID in the Guid heap (see Partition II, section 23.2.5) that identifies this instance of the module. The Mvid may be ignored on read by conforming implementations of the CLI. The Mvid should be newly generated for every module, using the algorithm specified in ISO/IEC 11578:1996 (Annex A) or another compatible algorithm.

NOTE

The term "GUID" stands for "Globally Unique IDentifier," a 16-byte-long number typically displayed using its hexadecimal encoding. A GUID may be generated by several well-known algorithms, including those used for UUIDs (Universally Unique IDentifiers) in RPC and CORBA, as well as CLSIDs, GUIDs, and IIDs in COM.


RATIONALE

While the VES itself makes no use of the Mvid, other tools (such as debuggers, which are outside the scope of this standard) rely on the fact that the Mvid almost always differs from one module to another.


The Generation, EncId, and EncBaseId columns can be written as zero, and can be ignored by conforming implementations of the CLI. The rows in the Module table result from .module directives in the Assembly (see Partition II, section 6.4).

This contains informative text only.


  1. The Module table shall contain one, and only one, row. [ERROR]

  2. Name shall index a non-null string. This string should match exactly any corresponding ModuleRef.Name string that resolves to this module. [ERROR]

    ANNOTATION

    Implementation-Specific (Microsoft): Name is limited to MAX_PATH_NAME. The format of Name is <file name>.<file extension> with no path or drive letter; on POSIX-compliant systems Name contains no colon, no forward-slash, no backslash.


  3. Mvid shall index a non-null GUID in the Guid heap. [ERROR]

End informative text


21.28 ModuleRef: 0x1A

The ModuleRef table has the following column:

  • Name (index into String heap)

The rows in the ModuleRef table result from .module extern directives in the Assembly (see Partition II, section 6.5).

This contains informative text only.


  1. Name shall index a non-null string in the String heap. This string shall enable the CLI to locate the target module (typically, it might name the file used to hold the module). [ERROR]

    ANNOTATION

    Implementation-Specific (Microsoft): Name is limited to MAX_PATH_NAME. The format of Name is <filename>.<extension> (e.g., "Foo.DLL" no drive letter, no path); on POSIX-compliant systems Name contains no colon, no forward-slash, and no backslash.


  2. There should be no duplicate rows. [WARNING]

  3. Name should match an entry in the Name column of the File table. Moreover, that entry shall enable the CLI to locate the target module (typically it might name the file used to hold the module). [ERROR]

End informative text


21.29 NestedClass: 0x29

The NestedClass table has the following columns:

  • NestedClass (index into the TypeDef table)

  • EnclosingClass (index into the TypeDef table)

The NestedClass table records which Type definitions are nested within which other Type definitions. In a typical high-level language, including ilasm, the nested class is defined as lexically "inside" the text of its enclosing Type.

This contains informative text only.


The NestedClass table records which Type definitions are nested within which other Type definitions. In a typical high-level language, the nested class is defined as lexically "inside" the text of its enclosing Type.

  1. The NestedClass table may contain zero or more rows.

  2. NestedClass shall index a valid row in the TypeDef table. [ERROR]

  3. EnclosingClass shall index a valid row in the TypeDef table (note, particularly, that it is not allowed to index the TypeRef table). [ERROR]

  4. There should be no duplicate rows (i.e., same values for NestedClass and EnclosingClass). [WARNING]

  5. A given Type can only be nested by one encloser. So, there cannot be two rows with the same value for NestedClass, but a different value for EnclosingClass. [ERROR]

  6. A given Type can "own" several different nested Types, so it is perfectly legal to have two or more rows with the same value for EnclosingClass, but different values for NestedClass.

End informative text


21.30 Param: 0x08

The Param table has the following columns:

  • Flags (a 2-byte bitmask of type ParamAttributes; see Partition II, section 22.1.12)

  • Sequence (a 2-byte constant)

  • Name (index into String heap)

Conceptually, every row in the Param table is owned by one, and only one, row in the MethodDef table.

The rows in the Param table result from the parameters in a method declaration (see Partition II, section 14.4), or from a .param attribute attached to a method (see Partition II, section 14.4.1).

This contains informative text only.


  1. The Param table may contain zero or more rows.

  2. Each row shall have one, and only one, owner row in the MethodDef table. [ERROR]

  3. Flags may have only those values set that are specified (all combinations valid). [ERROR]

  4. Sequence shall have a value >= 0 and <= number of parameters in owner method. A Sequence value of 0 refers to the owner method's return type; its parameters are then numbered from 1 onward. [ERROR]

  5. Successive rows of the Param table that are owned by the same method shall be ordered by increasing Sequence value although gaps in the sequence are allowed. [WARNING]

  6. If Flags.HasDefault = 1, then this row shall own exactly one row in the Constant table. [ERROR]

  7. If Flags.HasDefault = 0, then there shall be no rows in the Constant table owned by this row. [ERROR]

  8. Parameters cannot be given default values, so Flags.HasDefault shall be 0. [CLS]

  9. If Flags.FieldMarshal = 1, then this row shall own exactly one row in the FieldMarshal table. [ERROR]

  10. Name may be null or non-null.

  11. If Name is non-null, then it shall index a non-null string in the String heap. [WARNING]

ANNOTATION

Implementation-Specific (Microsoft): This string is limited to MAX_CLASS_NAME.


End informative text


21.31 Property: 0x17

Properties within metadata are best viewed as a means to gather together collections of methods defined on a class, give them a name, and not much else. The methods are typically get_ and set_ methods, already defined on the class, and inserted like any other methods into the MethodDef table. The association is held together by three separate tables:

graphics/05inf06.gif

Row 3 of the PropertyMap table indexes row 2 of the TypeDef table on the left (MyClass), while indexing row 4 of the Property table on the right the row for a property called Foo. This setup establishes that MyClass has a property called Foo. But what methods in the MethodDef table are gathered together as "belonging" to property Foo? That association is contained in the MethodSemantics table its row 2 indexes property Foo to the right, and row 2 in the MethodDef table to the left (a method called get_Foo). Also, row 3 of the MethodSemantics table indexes Foo to the right, and row 3 in the Method table to the left (a method called set_Foo). As the shading suggests, MyClass has another property, called Bar, with two methods, get_Bar and set_Bar.

Property tables do a little more than group together existing rows from other tables. The Property table has columns for Flags, Name (e.g., Foo and Bar in the example here) and Type. In addition, the MethodSemantics table has a column to record whether the method it points at is a set_, a get_, or other.

NOTE

The CLS (see Partition I [section 7]) refers to instance, virtual, and static properties. The signature of a property (from the Type column) can be used to distinguish a static property, since instance and virtual properties will have the HASTHIS bit set in the signature (see Partition II, section 22.2.1), while a static property will not. The distinction between an instance and a virtual property depends on the signature of the getter and setter methods, which the CLS requires to be either both virtual or both instance.


The Property (0x17) table has the following columns:

  • Flags (a 2-byte bitmask of type PropertyAttributes; see Partition II, section 22.1.13)

  • Name (index into String heap)

  • Type (index into Blob heap) (The name of this column is misleading. It does not index a TypeDef or TypeRef table instead it indexes the signature in the Blob heap of the Property.)

This contains informative text only.


  1. The Property table may contain zero or more rows.

  2. Each row shall have one, and only one, owner row in the PropertyMap table (as described above). [ERROR]

  3. PropFlags may have only those values set that are specified (all combinations valid). [ERROR]

  4. Name shall index a non-null string in the String heap. [ERROR]

    ANNOTATION

    Implementation-Specific (Microsoft): This string is limited to MAX_CLASS_NAME.


  5. The Name string shall be a valid CLS identifier. [CLS]

  6. Type shall index a non-null signature in the Blob heap. [ERROR]

  7. The signature indexed by Type shall be a valid signature for a property (i.e., low nibble of leading byte is 0x8). Apart from this leading byte, the signature is the same as the property's get_ method. [ERROR]

  8. Within the rows owned by a given row in the TypeDef table, there shall be no duplicates based upon Name+Type. [ERROR]

  9. There shall be no duplicate rows based upon Name, where Name fields are compared using CLS conflicting-identifier-rules (in particular, properties cannot be overloaded by their Type a class cannot have two properties, "int Foo" and "String Foo", for example). [CLS]

End informative text


21.32 PropertyMap: 0x15

The PropertyMap table has the following columns:

  • Parent (index into the TypeDef table)

  • PropertyList (index into the Property table). It marks the first of a contiguous run of Properties owned by Parent. The run continues to the smaller of:

    • The last row of the Property table

    • The next run of Properties, found by inspecting the PropertyList of the next row in this PropertyMap table

The PropertyMap and Property tables result from putting the .property directive on a class (see Partition II, section 16).

This contains informative text only.


  1. The PropertyMap table may contain zero or more rows.

  2. There shall be no duplicate rows, based upon Parent (a given class has only one "pointer" to the start of its property list). [ERROR]

  3. There shall be no duplicate rows, based upon PropertyList (different classes cannot share rows in the Property table). [ERROR]

End informative text


21.33 StandAloneSig: 0x11

Signatures are stored in the metadata Blob heap. In most cases, they are indexed by a column in some table Field.Signature, Method.Signature, MemberRef.Signature, etc. However, there are two cases that require a metadata token for a signature that is not indexed by any metadata table. The StandAloneSig table fulfills this need. It has just one column, that points to a Signature in the Blob heap.

The signature shall describe either:

  • A method code generators create a row in the StandAloneSig table for each occurrence of a calli CIL instruction. That row indexes the call-site signature for the function pointer operand of the calli instruction.

  • Local variables code generators create one row in the StandAloneSig table for each method, to describe all of its local variables. The .locals directive in ilasm generates a row in the StandAloneSig table.

The StandAloneSig table has the following column:

  • Signature (index into the Blob heap)

     
     Example (informative): // On encountering the calli instruction, ilasm generates a signature // in the blob heap (DEFAULT, ParamCount = 1, RetType = int32, Param1 = int32), // indexed by the StandAloneSig table: .assembly Test {} .method static int32 AddTen(int32) { ldarg.0   ldc.i4  10   add   ret } .class Test { .method static void main()   { .entrypoint     ldc.i4.1     ldftn int32 AddTen(int32)     calli int32(int32)     pop     ret   } } 

This contains informative text only.


  1. The StandAloneSig table may contain zero or more rows.

  2. Signature shall index a valid signature in the Blob heap. [ERROR]

  3. The signature "blob" indexed by Signature shall be a valid METHOD or LOCALS signature. [ERROR]

  4. Duplicate rows are allowed.

End informative text


21.34 TypeDef: 0x02

The TypeDef table has the following columns:

  • Flags (a 4-byte bitmask of type TypeAttributes; see Partition II, section 22.1.14)

  • Name (index into String heap)

  • Namespace (index into String heap)

  • Extends (index into TypeDef, TypeRef, or TypeSpec table; more precisely, a TypeDefOrRef coded index)

  • FieldList (index into Field table; it marks the first of a continguous run of Fields owned by this Type). The run continues to the smaller of:

    • The last row of the Field table

    • The next run of Fields, found by inspecting the FieldList of the next row in this TypeDef table

  • MethodList (index into the MethodDef table; it marks the first of a continguous run of Methods owned by this Type). The run continues to the smaller of:

    • The last row of the MethodDef table

    • The next run of Methods, found by inspecting the MethodList of the next row in this TypeDef table

Note that any type shall be one, and only one, of

  • Class (Flags.Interface = 0, and derives ultimately from System.Object)

  • Interface (Flags.Interface = 1)

  • Value type, derived ultimately from System.ValueType

For any given type, there are two separate, and quite distinct "inheritance" chains of pointers to other types (the pointers are actually implemented as indices into metadata tables). The two chains are:

  • Extension chain defined via the Extends column of the TypeDef table. Typically, a derived Class extends a base Class (always one, and only one, base Class).

  • Interface chains defined via the InterfaceImpl table. Typically, a Class implements zero, one, or more Interfaces.

These two chains (extension and interface) are always kept separate in metadata. The Extends chain represents one-to-one relations that is, one Class extends (or "derives from") exactly one other Class (called its immediate base Class). The Interface chains may represent one-to-many relations that is, one Class might well implement two or more Interfaces.

 
 Example (informative, written in C#): interface IA {void m1(int i);        } interface IB {void m2(int i, int j); } class C : IA, IB {   int f1, f2;   public void m1(int i)        {f1 = i;        }   public void m2(int i, int j) {f1 = i; f2 = j;} } // In metadata, Interface IA extends nothing; Interface IB // extends nothing; class C extends System.Object and implements // Interfaces IA and IB. 

An Interface can also "inherit" from one or more other Interfaces metadata stores those links via the InterfaceImpl table (the nomenclature is a little inappropriate here there is no "implementation" involved perhaps a clearer name might have been Interface table, or InterfaceInherit table).

 
 Example (informative, written in C#): interface IA          {void m1(int i);        } interface IB          {void m2(int i, int j); } interface IC : IA, IB {void m3(int i, int j, int k);} class C : IC {   int f1, f2, f3;   public void m1(int i)               {f1 = i;                }   public void m2(int i, int j)        {f1 = i; f2 = j;        }   public void m3(int i, int j, int k) {f1 = i; f2 = j; f3 = k;} } // In metadata, Interface IA extends nothing; Interface IB extends // nothing; Interface IC "inherits" Interfaces IA and IB (defined via // the InterfaceImpl table); Class C extends System.Object and // implements Interface IC (see InterfaceImpl table) 

There are also a few specialized types. One is the user-defined Enum which shall derive directly from System.Enum (via the Extends field).

Another slightly specialized type is a nested type which is declared in ilasm as lexically nested within an enclosing type declaration. Whether a type is nested can be determined by the value of its Flags.Visibility sub-field it shall be one of the set {NestedPublic, NestedPrivate, NestedFamily, NestedAssembly, NestedFamANDAssem, NestedFamORAssem}.

The roots of the inheritance hierarchies look like this:

graphics/05inf07.gif

There is one system-defined root System.Object. All Classes and ValueTypes shall derive, ultimately, from System.Object; Classes can derive from other Classes (through a single, non-looping chain) to any depth required. This Extends inheritance chain is shown with heavy arrows.

(See below for details of the System.Delegate Class).

Interfaces do not inherit from one another; however, they specify zero or more other interfaces which shall be implemented. The Interface requirement chain is shown as light, dashed arrows. This includes links between Interfaces and Classes/ValueTypes where the latter are said to implement that interface or interfaces.

Regular ValueTypes (i.e., excluding Enums see later) are defined as deriving directly from System.ValueType. Regular ValueTypes cannot be derived to a depth of more than one. (Another way to state this is that user-defined ValueTypes shall be sealed.) User-defined Enums shall derive directly from System.Enum. Enums cannot be derived to a depth of more than one below System.Enum. (Another way to state this is that user-defined Enums shall be sealed.) System.Enum derives directly from System.ValueType.

The hierarchy below System.Delegate is as follows:

graphics/05inf08.gif

User-defined delegates derive directly from System.MulticastDelegate. Delegates cannot be derived to a depth of more than one.

For the directives to declare types, see Partition II, section 9.

This contains informative text only.


  1. The TypeDef table may contain one or more rows. There is always one row (row zero) that represents the pseudo class that acts as parent for functions and variables defined at module scope.

  2. Flags:

    1. May have only those values set that are specified. [ERROR]

    2. Can set 0 or 1 of SequentialLayout and ExplicitLayout (if none set, then defaults to AutoLayout) [ERROR]

    3. Can set 0 or 1 of UnicodeClass and AutoClass (if none set, then defaults to AnsiClass) [ERROR]

      ANNOTATION

      Implementation-Specific (Microsoft): If RTSpecialName is set, then this Type is regarded as deleted (used in Edit&Continue and incremental compilation scenarios). Perform no checks on this Type or any of its members (the information is not physically deleted; it is just "flagged" as logically deleted). Note: this situation can only be seen on in-memory metadata it is not persisted to disk, and therefore it is irrelevant to checks done by an offline tool.

      If Import is set (denotes a Type defined via the tlbimp tool), then all the methods owned by this Type shall have their Method.RVA = 0. [ERROR]


    4. If Flags.HasSecurity = 1, then at least one of the following conditions shall be true: [ERROR]

      • This Type owns at least one row in the DeclSecurity table.

      • This Type has a custom attribute called SuppressUnmanagedCodeSecurityAttribute.

    5. If this Type owns one (or more) rows in the DeclSecurity table, then Flags.HasSecurity shall be 1. [ERROR]

    6. If this Type has a custom attribute called SuppressUnmanagedCodeSecurityAttribute, then Flags.HasSecurity shall be 1. [ERROR]

    7. Note that it is legal for an Interface to have HasSecurity set. However, the security system ignores any permission requests attached to that Interface.

  3. Name shall index a non-null string in the String heap. [ERROR]

    ANNOTATION

    Implementation-Specific (Microsoft): This string is limited to MAX_CLASS_NAME.


  4. The Name string shall be a valid CLS identifier. [CLS]

  5. Namespace may be null or non-null.

  6. If non-null, then Namespace shall index a non-null string in the String heap. [ERROR]

    ANNOTATION

    Implementation-Specific (Microsoft): This string is limited to MAX_CLASS_NAME. Also, the concatenated TypeNamespace+"."+TypeName shall be less than MAX_ CLASS_NAME.


  7. If non-null, Namespace's string shall be a valid CLS identifier. [CLS]

  8. Every Class (with the sole exception of System.Object) shall extend one, and only one, other Class so Extends for a Class shall be non-null. [ERROR]

  9. System.Object shall have an Extends value of null. [ERROR]

  10. System.ValueType shall have an Extends value of System.Object. [ERROR]

  11. With the sole exception of System.Object, for any Class, Extends shall index a valid row in the TypeDef or TypeRef table, where valid means 1 <= row <= rowcount. In addition, that row itself shall be a Class (not an Interface or ValueType). In addition, that base Class shall not be sealed (its Flags.Sealed shall be 0). [ERROR]

    ANNOTATION

    Implementation-Specific (Microsoft): Extends may index a row in the TypeSpec table this is an extension for prototyping parametric-polymorphism. [WARNING]


  12. A Class cannot extend itself, or any of its children (i.e., its derived Classes), since this would introduce loops in the hierarchy tree. [ERROR]

  13. An Interface never extends another Type so Extends shall be null (Interfaces do implement other Interfaces, but recall that this relationship is captured via the InterfaceImpl table, rather than the Extends column). [ERROR]

  14. FieldList can be null or non-null.

  15. A Class or Interface may "own" zero or more fields.

  16. A ValueType shall have a non-zero size either by defining at least one field, or by providing a non-zero ClassSize. [ERROR]

  17. If FieldList is non-null, it shall index a valid row in the Field table, where valid means 1 <= row <= rowcount+1. [ERROR]

  18. MethodList can be null or non-null.

  19. A Type may "own" zero or more methods.

  20. The runtime size of a ValueType shall not exceed 1 MByte (0x100000 bytes). [ERROR]

    ANNOTATION

    Implementation-Specific (Microsoft): The current implementation actually allows 0x3F0000 bytes, but this size may be reduced in future.


  21. If MethodList is non-null, it shall index a valid row in the MethodDef table, where valid means 1 <= row <= rowcount+1. [ERROR]

  22. A Class which has one or more abstract methods cannot be instantiated, and shall have Flags.Abstract = 1. Note that the methods owned by the class include all of those inherited from its base class and interfaces it implements, plus those defined via its Method List. (The CLI shall analyze class definitions at runtime; if it finds a class to have one or more abstract methods, but has Flags.Abstract = 0, it will throw an exception.) [ERROR]

  23. An Interface shall have Flags.Abstract = 1. [ERROR]

  24. It is legal for an abstract Type to have a constructor method (i.e., a method named .ctor).

  25. Any non-abstract Type (i.e., Flags.Abstract = 0) shall provide an implementation (body) for every method its contract requires. Its methods may be inherited from its base class, from the interfaces it implements, or defined by itself. The implementations may be inherited from its base class or defined by itself. [ERROR]

  26. An Interface (Flags.Interface == 1) can own static fields (Field.Static == 1) but cannot own instance fields (Field.Static == 0). [ERROR]

  27. An Interface cannot be sealed (if Flags.Interface == 1, then Flags.Sealed shall be 0). [ERROR]

  28. All of the methods owned by an Interface (Flags.Interface == 1) shall be abstract (Flags.Abstract == 1). [ERROR]

  29. There shall be no duplicate rows in the TypeDef table, based on Namespace+Name (unless this is a nested type see below). [ERROR]

  30. If this is a nested type, there shall be no duplicate row in the TypeDef table, based upon Namespace+Name+OwnerRowInNestedClassTable. [ERROR]

  31. There shall be no duplicate rows, where Namespace+Name fields are compared using CLS conflicting-identifier-rules (unless this is a nested type see below). [CLS]

  32. If this is a nested type, there shall be no duplicate rows, based upon Namespace+ Name+OwnerRowInNestedClassTable and where Namespace+Name fields are compared using CLS conflicting-identifier-rules. [CLS]

  33. If Extends = System.Enum (i.e., type is a user-defined Enum), then:

    1. [It] shall be sealed (Sealed = 1). [ERROR]

    2. [It] shall not have any methods of its own (MethodList chain shall be zero length). [ERROR]

    3. [It] shall not implement any interfaces (no entries in InterfaceImpl table for this type). [ERROR]

    4. [It] shall not have any properties. [ERROR]

    5. [It] shall not have any events. [ERROR]

    6. Any static fields shall be literal (have Flags.Literal = 1). [ERROR]

    7. [It] shall have at least one static, literal field. If more than one, they shall all be of the same type. Any such static literal fields shall be of the type of the Enum. [CLS]

    8. [There] shall be at least one instance field, of integral type. [ERROR]

    9. [There] shall be exactly one instance field. [CLS]

    10. The Name string of the instance field shall be "value__"; it shall be marked RTSpecialName; its type shall be one of (see Partition II, section 22.1.15): [CLS]

      • ELEMENT_TYPE_U1

      • ELEMENT_TYPE_I2

      • ELEMENT_TYPE_I4

      • ELEMENT_TYPE_I8

    11. [There] shall be no other members (i.e., apart from any static literals, and the one instance field called "value__" ). [CLS]

  34. A Nested type (defined above) shall own exactly one row in the NestedClass table where "owns" means a row in that NestedClass table whose NestedClass column holds the TypeDef token for this type definition. [ERROR]

  35. A ValueType shall be sealed. [ERROR]

End informative text


21.35 TypeRef: 0x01

The TypeRef table has the following columns:

  • ResolutionScope (index into Module, ModuleRef, AssemblyRef, or TypeRef tables, or null; more precisely, a ResolutionScope coded index)

  • Name (index into String heap)

  • Namespace (index into String heap)

This contains informative text only.


  1. ResolutionScope shall be exactly one of:

    null in this case, there shall be a row in the ExportedType table for this Type its Implementation field shall contain a File token or an AssemblyRef token that says where the type is defined. [ERROR]

    A TypeRef token, if this is a nested type (which can be determined by, for example, inspecting the Flags column in its TypeDef table the accessibility subfield is one of the tdNestedXXX set). [ERROR]

    A ModuleRef token, if the target type is defined in another module within the same Assembly as this one. [ERROR]

    A Module token, if the target type is defined in the current module this should not occur in a CLI ("compressed metadata") module. [WARNING]

    An AssemblyRef token, if the target type is defined in a different Assembly from the current module. [ERROR]

  2. Name shall index a non-null string in the String heap. [ERROR]

    ANNOTATION

    Implementation-Specific (Microsoft): This string is limited to MAX_CLASS_NAME.


  3. Namespace may be null or non-null.

  4. If non-null, Namespace shall index a non-null string in the String heap. [ERROR]

    ANNOTATION

    Implementation-Specific (Microsoft): This string is limited to MAX_CLASS_NAME. Also, the concatenated TypeNamespace+"."+TypeName shall be less than MAX_ CLASS_NAME.


  5. The Name string shall be a valid CLS identifier. [CLS]

  6. There shall be no duplicate rows, where a duplicate has the same ResolutionScope, Name, and Namespace. [ERROR]

  7. There shall be no duplicate rows, where Name and Namespace fields are compared using CLS conflicting-identifier-rules. [CLS]

End informative text


21.36 TypeSpec: 0x1B

The TypeSpec table has just one column, which indexes the specification of a Type, stored in the Blob heap. This provides a metadata token for that Type (rather than simply an index into the Blob heap) this is required, typically, for array operations creating, or calling methods on the array class.

The TypeSpec table has the following column:

  • Signature (index into the Blob heap, where the blob is formatted as specified in Partition II, section 22.2.14)

Note that TypeSpec tokens can be used with any of the CIL instructions that take a TypeDef or TypeRef token specifically:

castclass, cpobj, initobj, isinst, ldelema, ldobj, mkrefany, newarr, refanyval, sizeof, stobj, box, unbox

This contains informative text only.


  1. The TypeSpec table may contain zero or more rows.

  2. Signature shall index a valid Type specification in the Blob heap. [ERROR]

  3. There shall be no duplicate rows, based upon Signature. [ERROR]

End informative text




The Common Language Infrastructure Annotated Standard (Microsoft. NET Development Series)
The Common Language Infrastructure Annotated Standard (Microsoft. NET Development Series)
ISBN: N/A
EAN: N/A
Year: 2002
Pages: 121

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