La definición de nombres simbólicos para las constantes en un programa facilita la lectura y simplifica el proceso de mantenimiento del programa en el futuro. Un método es definir una enumeración, que asocia un conjunto de números enteros con un conjunto de identificadores denominados enumeradores que el compilador reconoce y sustituye por el valor del número entero correspondiente. Una enumeración se define utilizando una declaración como:
enum colors { RED, GREEN, BLUE };
El primer enumerador de la enumeración, RED, tiene asignado el valor cero y cada siguiente identificador tiene asignado el siguiente valor de número entero. También puede especificar un valor de número entero explícito para cualquier enumerador añadiéndole un sufijo con un signo igual y una constante de número entero, como en el siguiente ejemplo:
enum colors { RED = 7, GREEN = 9, BLUE };
El compilador asigna el valor 10 al enumerador BLUE porque no tiene ningún valor especificado y porque el enumerador previo se establece en 9. Tras definirse una enumeración, los enumeradores se pueden utilizar en cualquier parte de un programa D en que se pueda utilizar una constante entera. Además, la enumeración enum colors también se define como un tipo que es equivalente a un int. El compilador de D también permitirá utilizar una variable de tipo enum en cualquier lugar donde se pueda utilizar un int, y permitirá asignar cualquier valor de número entero a una variable del tipo enum. También puede omitir el nombre enum en la declaración si el nombre de tipo no es necesario.
Los enumeradores son visibles en todas las siguientes cláusulas y declaraciones del programa, por lo que no puede definirse el mismo identificador de enumerador en más de una enumeración. Sin embargo, puede definir más de un enumerador que tenga el mismo o distinto valor en la misma enumeración o en una enumeración diferente. También puede asignar números enteros que no tengan un enumerador correspondiente a una variable del tipo enumeración.
La sintaxis de la enumeración de D es igual a la sintaxis correspondiente en ANSI-C. D también proporciona acceso a las enumeraciones definidas en el núcleo del sistema operativo y sus módulos cargables, pero estos enumeradores no son visibles globalmente en el programa D. Los enumeradores de núcleo sólo son visibles cuando se utilizan como un argumento para uno de los operadores de comparación binarios al compararlos con un objeto del tipo enumeración correspondiente. Por ejemplo, la función uiomove(9F) tiene un parámetro de tipo enum uio_rw definido de la siguiente manera:
enum uio_rw { UIO_READ, UIO_WRITE };
Los enumeradores UIO_READ y UIO_WRITE no se ven normalmente en el programa D, pero puede promocionarlos a la visibilidad global comparando un valor de tipo enum uio_rw, como se muestra en la siguiente cláusula de ejemplo:
fbt::uiomove:entry /args[2] == UIO_WRITE/ { ... }
Este ejemplo realiza un seguimiento de las llamadas a la función uiomove(9F) para las solicitudes de escritura comparando args[2], una variable de tipo enum uio_rw, con el enumerador UIO_WRITE. Debido a que el argumento de la izquierda es del tipo enumeración, el compilador de D busca la enumeración cuando intenta resolver el identificador de la derecha. Esta función protege los programas D contra los conflictos no detectados de nombres de identificadores con una larga lista de enumeraciones definidas en el núcleo del sistema operativo.