I have used the MetadataSupport library in X++ to help get metadata information for tables, menu items, and data entities in the past. I have also used it for enums but recently found an issue when dealing with enum extensions.
I initially wrote the logic to get enum metadata information like this:
Which seems to work just fine, until you find an enum that contains a base enum extension, for example LedgerJournalType:
We can see in this case the both ‘Daily’ and ‘RevenueRecognition’ share a value of 0, which can’t happen so what is going on?
Deterministic vs Nondeterministic Enum Values
In the AX 2012 world, we used deterministic enum values where the enum value was set at design time. In D365FO, we now have to extend enums if we want to modify them so how does D365FO handle this? They use nondeterministic values to allow for extending enums which means that the enum value is actually set at runtime (or technically when a database sync is executed). These values are then stored in the database in thetables.
We can see if a enum is being used in a nondeterministic fashion by looking at the UseEnumValue property on the enum itself. For example, the LedgerJournalType enum is set to be nondeterministic because it has UseEnumValue equal to No.
If we go the the EnumValueTable and look up what the actual enum values are we can see that we actually do not have duplicate enum values but instead Revenue Recognition is actually using the value of 5 instead of 0.
So it appears the MetadataSupport library does not look at the value of the enum extensions as they are generated at runtime instead of design time and it defaults these values to be 0 instead of their actual value.
How Do We Get Nondeterministic Enum Values Programmatically?
So if the MetadataSupport library isn’t giving the correct enum values, how can we get them programmatically? We can utilize the SysDictEnum object like in the example below:
This class correctly gathers the enum information regardless if its a deterministic or nondeterministic enum.
So what can we take away from this?
The first thing is that you should NEVER compare enums to an integer value using something like equals or less than/greater than can lead to incorrect logic being applied as some enums will not have the same values across environments.
If at all possible be sure that all comparisons are against the enum itself:
LedgerJournalType value = LedgerJournalType.Daily Use: if(value == LedgerJournalType.Daily) Do not use: if(value == 0)