Prefer Enum over Option type
Option fields cannot be extended by other extensions. When another app needs to add a value to an Option field — a new document status, a new shipment method — there is no supported mechanism. The extension developer must duplicate the field or build workarounds. Enum types solve this: any extension can add values through an enumextension object.
Options also encourage fragile code patterns. Their members are positional, so assignments like Rec.Status := 2 compile silently. When members are reordered or inserted, these magic-number references break without a compiler warning. Enums enforce named references and provide stronger IntelliSense support.
Replace Option declarations with an Enum object and reference it in fields, parameters, return values, and variables.
Example
table 50100 "Sales Document"
{
fields
{
field(1; Status; Option) // Prefer Enum over Option type [LC0088]
{
Caption = 'Status';
OptionMembers = Open,Released,"Pending Approval";
}
}
}Create an Enum object with the same members and reference it as the field type:
enum 50100 "Sales Document Status"
{
value(0; Open) { }
value(1; Released) { }
value(2; "Pending Approval") { }
}
table 50100 "Sales Document"
{
fields
{
field(1; Status; Enum "Sales Document Status")
{
Caption = 'Status';
}
}
}The rule applies equally to parameters, return values, and Option variables.
Exception
The rule does not trigger in scenarios where the Option type is dictated by external constraints:
- CDS tables: Tables with
TableType = CDSare excluded. The AL Table Proxy Generator converts Dataverse OptionSets to Option types automatically; replacing them with Enums would break the proxy mapping. - Event subscriber parameters: When subscribing to an event whose publisher signature uses an Option parameter, the subscriber must match the publisher’s type.
- FlowFields over Option sources: A FlowField that calculates over a source field of type Option cannot use an Enum when the source field remains an Option.
- Variables passed to dependency methods: Local or global Option variables that are passed as arguments to procedures defined in a dependency extension are excluded. The dependency’s API signature dictates the variable type.
To suppress the diagnostic in other cases, use a pragma directive:
#pragma warning disable LC0088 // Option required by legacy integration contract
field(1; "Legacy Status"; Option)
{
OptionMembers = Active,Inactive;
}
#pragma warning restore LC0088
When Option could a valid choice
The rule does not raise a diagnostic when an Option variable is passed to a method defined in a dependency extension. Raising the diagnostic in this case could push developers toward replacing the named Option members with raw integers — e.g. ReservationManagement.SetItemTrackingHandling(1); — which is harder to read and more error-prone than the Option it replaces.
internal procedure DeleteReservEntries()
var
ReservationManagement: Codeunit "Reservation Management";
Mode: Option "None","Allow deletion",Match;
begin
ReservationManagement.SetReservSource(Rec);
ReservationManagement.SetItemTrackingHandling(Mode::"Allow deletion");
ReservationManagement.DeleteReservEntries(true, 0);
end;CDS tables
The rule excludes tables with the TableType property set to CDS. The AL Table Proxy Generator converts an OptionSet from Dataverse to an Option type in Business Central. See the statecode field in the example below.
table 50100 "Dataverse Project PTE"
{
ExternalName = 'prefix_project';
TableType = CDS;
Caption = 'Project';
fields
{
field(1; prefix_projectId; Guid)
{
ExternalName = 'prefix_projectid';
ExternalType = 'Uniqueidentifier';
ExternalAccess = Insert;
Description = 'Unique identifier for entity instances';
Caption = 'Project';
}
field(2; prefix_name; Text[100])
{
ExternalName = 'prefix_name';
ExternalType = 'String';
Description = 'The name of the custom entity.';
Caption = 'Name';
}
field(25; statecode; Option)
{
ExternalName = 'statecode';
ExternalType = 'State';
ExternalAccess = Modify;
Description = 'Status of the Project';
Caption = 'Status';
InitValue = " ";
OptionMembers = " ",Active,Inactive;
OptionOrdinalValues = -1, 0, 1;
}
}
}See also
- Extensible Enums on Microsoft Learn
- Option data type on Microsoft Learn
- It’s time to Enumify your Option fields in AL and Business Central by Erik Hougaard
- You should always use Option instead of Enum, unless … by Erik Hougaard