.NET programs can make use of some special types that are not
directly defined in assemblies but are closely related to types defined in
assemblies. These types, which often arise as parameters or local
variables, have TypeNode.IsStructural set to
true.
Array types, such as byte[], are
represented by the ArrayType node. The
ElementType property reflects the
underlying type of the elements in the array.
Parameters that pass a value by reference (ref
and out in C#, ByRef in VB.NET) are
represented by the Reference node. The
BaseType property reflects the underlying
type of the referent.
Pointers, which arise in unsafe C# and C++
code, are represented by the Pointer node.
The BaseType property reflects the type
of the pointer's target.
Function pointers, which arise in C++ code, are represented
by the FunctionPointer node. It has
ParameterType and
ReturnType properties that describe the
function signature.
Generic type parameters (such as T,
K, and V) are
represented by TypeParameter and
ClassParameter nodes. If the type parameter
has a constrained base type, ClassParameter
is used and the base type is available through the
BaseType property. Otherwise,
TypeParameter is used and
BaseType is null. If the
type parameter is constrained to implement one or more interfaces,
these interfaces are available through the
Interfaces property.
So-called "constructed generic types", or generic types with
their type parameters bound to specific types, such as
List<String> are also considered
structural. These are represented by an ordinary type node, such
as ClassNode or
Struct. The
Template property identifies the related
unconstructed generic type. The
TemplateArguments property provides the
specific type arguments that were bound against this template (in
the List<String> example, these would
be a ClassNode for
String).
Type modifiers tend to appear when using C++. There are two
kinds of type modifier nodes,
OptionalModifier and
RequiredModifier, both of which inherit
from TypeModifier. These nodes give the
type of the modifier as the Modifier
property and the type being modified as the
ModifiedType property. For example, in
C++, a variable declared as const int x would have an
Modifier that corresponds to the
System.Runtime.CompilerServices.IsConst
class and a ModifiedType that corresponds to the
System.Int32 structure.