Getting dynamic runtime type information

The simplest form of reflection available in D is runtime type information, which is available through the typeid() operator. It is used extensively by the druntime implementation and is integral to the safe dynamic casting of classes.

How to do it…

Let's execute the following steps to get dynamic runtime type information:

  1. In most cases, you only need to write typeid(variable_or_type).
  2. If you want to get a dynamic class type through an interface, first cast it to Object, check for null, and then use typeid(the_casted_object).

The code is as follows:

TypeInfo typeInfoAboutInt = typeid(int);
typeInfoAboutInt = typeid(1); // also works

How it works…

The compiler and the runtime library automatically define type information for all types. This information is found in static TypeInfo objects, which is retrieved by reference using the typeid() operator. The definition of the TypeInfo interface is found in the automatically-imported object.d module of druntime, and thus it is always available to D programs.

TypeInfo is tailored for druntime's needs. It contains functions for:

  • Hashing, equality, and comparison (needed for associative arrays).
  • Construction, destruction, copying, and garbage collection flags (needed for the new operator and built-in array operators).
  • Getting the next type out of a compound type. For example, typeid(int*).next is typeid(int). typeid(int*) gives information about a pointer, which points to the next type.
  • An internal extension hook, intended for future garbage collection improvements.

Classes and interfaces have to get additional functions:

  • The class' name
  • The class' base class and interfaces
  • The class' virtual function table
  • The class' initial memory image
  • Searching and creating the class, if it has a simple constructor

These methods are vital to the proper functioning of classes. They enable safe dynamic casting from base class to derived class, proper object construction, and automatic implementation of toString, which works without being explicitly overridden in every class you write.

The TypeInfo references are only stored with the data of class objects (specifically, the first hidden virtual function entry for each object stores a reference to the correct TypeInfo reference). With all other types, typeid yields a reference based on the static type. This means that you cannot retrieve the runtime type information from a void* or void[], as shown in the following code:

void main() {
     int[] a;
     arrayType(a);
}
void arrayType(void[] arr) {
     // assert(typeid(arr) == typeid(int[])); // FAILS
     // The following passes because non-class typeid is based on static type
     assert(typeid(arr) == typeid(void[]));
}

If you want to work with void* in a type-safe way, it is important to explicitly pair a TypeInfo object with it. This is how the druntime functions work, also some of the language features' non-template D variadic functions work in the same way.

Tip

Templates are generally better at both type safety and efficiency than runtime information. You should only use TypeInfo based typing in functions when you have special ABI requirements. The void* and TypeInfo pairs are used in druntime primarily for legacy reasons; the library was designed before D had templates.

Static types are also used with interfaces: typeid(some_object_via_interface) and is typeid(the_interface_you_are_using);. In order to get the dynamic type of the object behind the interface, you will have to first cast it to an object, and then cast it from the object to the derived class.

Note

Casting an interface to the object might fail because not all interfaces are D objects. It might also be a C++ or COM object. Thus, any time you cast an interface to object, you ought to check for the null value.

To compare types at runtime, you may use either the == operator or the is operator on TypeInfo. Since there's only one instantiation for each type, you can always rely on the comparison operators.

See also

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.137.186.178