X++ — the language behind Dynamics 365 Finance and Operations
What X++ is, where it came from, and how it's used in F&O — language features, the application object tree, and the modern developer workflow with Visual Studio.
Dynamics 365 Finance and Operations runs on X++ — a proprietary object-oriented language that's been the foundation of the AX / F&O product family since the 1990s. Modern X++ feels like a hybrid of Java, C#, and SQL; for developers extending F&O, learning X++ is the prerequisite for serious work.
Origin. Born in the 1990s with Axapta (later acquired by Microsoft, becoming Dynamics AX, then Dynamics 365 F&O). Inspired by Object Pascal and Java; designed for business applications with native data access.
Modern X++. As of F&O wave 2 2026:
- Compiled to IL — runs on .NET CIL after compilation.
- Visual Studio development — primary IDE; AOT (Application Object Tree) navigated visually.
- Modern syntax — closures, attributes, generics (limited).
- Native SQL —
select * from custTable where ...works inline.
The language has evolved significantly; modern X++ is more Java/C#-like than its Pascal heritage.
Core constructs.
- Classes with inheritance.
- Tables as first-class objects (extending DataObject).
- Views, queries, maps.
- Forms with event-driven controllers.
- Reports (mostly legacy; SSRS for newer).
- Workflows.
- Services.
The Application Object Tree (AOT) is the namespace; all artefacts live in it organised by type.
Native SQL.
CustTable custTable;
select firstonly custTable
where custTable.AccountNum == '4000';
The select statement is integrated with the language; the compiler generates SQL.
Table buffers. A table variable represents a row buffer:
CustTable custTable;
custTable.AccountNum = 'NEW001';
custTable.Name = 'New Customer';
custTable.insert();
custTable is a buffer; methods like .insert(), .update(), .delete() operate on the buffer's data.
Extension model.
- Chain of Command (CoC) — extension method wrappers around base methods.
- Event handlers — subscribe to pre/post events on base methods.
- Table extensions — add fields, methods, events to existing tables.
- Form extensions — add controls to existing forms.
No direct base code modification; extensions only. This enables Microsoft to update base code without breaking customisations.
Visual Studio integration.
- Visual Studio with F&O developer tools installed.
- Browse AOT, edit X++, compile, deploy.
- Debugger built in.
- Source control via Azure DevOps git.
The development experience has improved dramatically vs the old MorphX environment.
Classes vs tables. Two distinct concepts:
- Class — code logic, business rules.
- Table — data storage.
A class operates on table buffers; a table can have methods too but typically lightweight.
The macro system. X++ has a C-like preprocessor:
#define.MaxLength 100
Used heavily in older code; less in modern. Macros pollute namespaces and are deprecated for most uses.
Currency and value handling. Built-in types for financial data:
- Real — decimal numbers.
- Currency — currency-aware decimals.
- Amount — financial amounts with currency.
Plus rounding helpers, conversion functions; financial math is first-class.
Common patterns.
Iterate records:
while select custTable
where custTable.CustGroup == 'PREMIUM'
{
info(strFmt("Customer: %1", custTable.Name));
}
Insert with transaction:
ttsbegin;
CustTable.insert();
ttscommit;
Method call with exception:
try {
someMethod();
}
catch {
error("Something failed");
}
Performance considerations.
- Set-based vs record-based operations — set-based much faster.
- Index utilisation — define indexes for common queries.
- Cache hints —
forupdate,notexistsjoinfor performance. - Batch processing — for long operations.
Modern X++ features.
- Closures (anonymous methods).
- Attributes for metadata.
- Reflection via SysDictType, SysDictClass.
Comparison with C#. X++ is similar to C# in many ways but:
- Less generic (limited generics).
- Native SQL integration.
- Domain-specific for ERP.
- Smaller community.
C# developers picking up X++ usually feel productive within weeks.
Extension considerations.
- Sandboxed dev environments — Tier 1 VMs.
- Build server — compiles and packages.
- Deployment via LCS or Azure DevOps — to upper environments.
The deployment story is more complex than BC's AL; F&O development is heavier infrastructure.
Common pitfalls.
- Modifying base code. Cardinal sin; updates break.
- Heavy in-loop DB calls — performance dies.
- No transaction control. Inconsistent state on errors.
- Skipping CoC pattern — using events when CoC is cleaner.
- Macro overuse — modern code prefers methods and constants.
Strategic positioning. X++ is here to stay — F&O is built on it; replacing it would mean a rewrite of millions of lines of base application code. Microsoft continues to invest: modernisation each wave, better tooling, Copilot-assisted X++ development emerging. Developers committing to F&O development should treat X++ as a long-term investment; the language isn't going anywhere. Mastery requires the language plus the AOT plus the patterns; investment time is meaningful but the resulting capability is in demand.
Related guides
- Chain of Command extension model in F&OHow Chain of Command lets X++ developers extend F&O standard logic safely — wrap methods, call next, and the upgrade-safe pattern.
- Custom services and OData endpoints in F&OHow to expose Dynamics 365 Finance / SCM functionality to external systems — custom services in X++, OData endpoints from data entities, authentication and limits.
- Form extensions in Dynamics 365 Finance and OperationsHow to extend forms in F&O — extending standard forms, adding controls and groups, handling events, and avoiding common form-extension pitfalls.
- 1099 reporting for US in Dynamics 365 FinanceHow F&O handles US 1099 reporting — vendor classification, 1099 boxes, year-end generation, e-filing, and the recipient-copy distribution.
- Alerts and notifications in Dynamics 365 FinanceHow F&O's alert framework surfaces important events — alert rules, due-date triggers, change events, delivery to action centre and email.