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, as shown below:
Row 3 of the PropertyMap table indexes row 2 of the TypeDef table on the left (MyClass
), whilst 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 MethodDef 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 (eg 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) 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 (§II.23.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. end note]
The Property (0x17) table has the following columns:
-
Flags (a 2-byte bitmask of type PropertyAttributes, §II.23.1.14)
-
Name (an index into the String heap)
-
Type (an index into the 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.
-
Property table can contain zero or more rows
-
Each row shall have one, and only one, owner row in the PropertyMap table (as described above) [ERROR]
-
PropFlags shall have only those values set that are specified (all combinations valid) [ERROR]
-
Name shall index a non-empty string in the String heap [ERROR]
-
The Name string shall be a valid CLS identifier [CLS]
-
Type shall index a non-null signature in the Blob heap [ERROR]
-
The signature indexed by Type shall be a valid signature for a property (ie, low nibble of leading byte is 0x8). Apart from this leading byte, the signature is the same as the property's get_ method [ERROR]
-
Within the rows owned by a given row in the TypeDef table, there shall be no duplicates based upon Name+Type [ERROR]
-
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.