Code Examples
Practical X++ code patterns for working with base enumerations and extended data types.
Base Enum Usage
SalesStatus status = SalesStatus::Invoiced;
if (salesTable.SalesStatus == SalesStatus::Open)
{
info("Order is still open");
}
Always compare against the symbolic constant, never a raw integer:
// Correct
select salesTable where salesTable.SalesStatus == SalesStatus::Invoiced;
// Incorrect — fragile if values change
select salesTable where salesTable.SalesStatus == 3;
Handling Extensible Enums
When an enum is extensible, consuming code should handle unknown values in switch statements:
switch (salesTable.SalesStatus)
{
case SalesStatus::Open:
// handle open
break;
case SalesStatus::Invoiced:
// handle invoiced
break;
default:
// Handle values added by extensions gracefully
warning(strFmt("Unhandled status: %1", salesTable.SalesStatus));
break;
}
Iterating Over Enum Values
DictEnum dictEnum = new DictEnum(enumNum(SalesStatus));
int i;
for (i = 0; i < dictEnum.values(); i++)
{
info(strFmt("Name: %1, Value: %2, Label: %3",
dictEnum.index2Name(i),
dictEnum.index2Value(i),
dictEnum.index2Label(i)));
}
Converting Between Enum and Integer
// Enum to integer
int statusInt = enum2int(SalesStatus::Invoiced);
// Integer to enum
SalesStatus status = int2enum(statusInt);
// Enum to string (symbolic name)
str statusName = enum2Str(SalesStatus::Invoiced); // "Invoiced"
// String to enum
SalesStatus fromStr = str2Enum(SalesStatus::Open, "Invoiced");
Using Enums in Select Statements
SalesTable salesTable;
// Filter by enum value
select firstonly salesTable
where salesTable.SalesStatus == SalesStatus::Open;
// Use enum ranges
select count(RecId) from salesTable
where salesTable.SalesStatus >= SalesStatus::Open
&& salesTable.SalesStatus <= SalesStatus::Invoiced;
EDT Variable Declarations
// Declaring variables using EDTs
CustAccount customerAccount;
TransDate transactionDate;
AmountMST amount;
ItemId itemId;
// EDT types provide semantic meaning in method signatures
public void postInvoice(CustAccount _custAccount, TransDate _transDate, AmountMST _amount)
{
// Parameters are self-documenting via their EDT names
}
EDT Inheritance in Practice
// CustAccount extends AccountNum extends EDT String
// Assignment from child to parent is always valid:
CustAccount custAcct = "CUST-001";
AccountNum acctNum = custAcct;
// Define a method that accepts the parent EDT
public void processAccount(AccountNum _accountNum)
{
info(strFmt("Processing account: %1", _accountNum));
}
// Call it with a child EDT — valid because CustAccount extends AccountNum
this.processAccount(custAcct);
Working with EDT Relations
// When CustAccount EDT has a relation to CustTable.AccountNum,
// fields using CustAccount EDT automatically get a lookup to CustTable.
CustTable custTable = CustTable::find(salesTable.CustAccount);
info(strFmt("Customer name: %1", custTable.name()));
Inspecting EDT Metadata at Runtime
DictType dictType = new DictType(extendedTypeNum(CustAccount));
info(strFmt("EDT Name: %1", dictType.name()));
info(strFmt("Label: %1", dictType.label()));
info(strFmt("Help Text: %1", dictType.help()));
info(strFmt("String Size: %1", dictType.stringLen()));
info(strFmt("Extends: %1", dictType.extendedBy() ? "Yes" : "No"));