**
X++ basics for D365 F&O developers: variables, classes, and methods
**
Every technical topic in Dynamics 365 Finance & Operations — extensions, event handlers, data entities, batch jobs — sits on top of the same foundation: the X++ language. Today we cover the three building blocks you'll use in literally every piece of X++ code you write: variables, classes, and methods.
If you've worked with C# or Java before, most of this will feel familiar. X++ is an object-oriented language with a syntax deliberately close to C#, with a few D365-specific extensions layered on top (extended data types, table buffers, and so on).
- Variables: typed containers for data A variable in X++ is a named, typed storage location. You declare it with a type, then a name:
str custAccount; // string
int salesQty; // whole number
real unitPrice; // decimal number
boolean isValid; // true/false
date orderDate; // calendar date
The common primitive types you'll use constantly:
Type Holds Example
str Text "US-001"
int Whole numbers 10
real Decimal numbers 25.50
boolean True or false true
date Calendar dates 1/1/2026
X++ also uses extended data types (EDTs) — custom types built on these primitives that add labels, validation, and relations. You'll meet those properly on Day 2, but know they exist: a field like CustAccount is really an EDT wrapping str.
- Classes: bundling data with behavior A class is a blueprint. It groups related fields (the variables that hold an object's data) together with the methods (the actions that operate on that data). Here's a minimal class:
class SalesOrderHelper
{
str custAccount;
int salesQty;
real unitPrice;
}
This class has no behavior yet — just three fields. The diagram below shows the two halves every class has: the data it stores, and the actions it can perform.
- Methods: giving the class behavior Methods are functions that belong to a class. They can read and change the class's fields directly, and they define what the class is actually able to do. Let's add three methods to SalesOrderHelper:
class SalesOrderHelper
{
str custAccount;
int salesQty;
real unitPrice;
public void init(str _custAccount, int _qty, real _price)
{
custAccount = _custAccount;
salesQty = _qty;
unitPrice = _price;
}
public real calcTotal()
{
return salesQty * unitPrice;
}
public boolean validate()
{
return (salesQty > 0 && unitPrice > 0);
}
}
init() sets the fields when the object is first created.
calcTotal() reads two fields and returns a computed value.
validate() checks the object's data is sane before you trust it.
Mental model: a class is a shape (the fields it declares). An object is a specific instance of that shape, with its own values. You can create as many SalesOrderHelper objects as you like — each keeps its own custAccount, salesQty, and unitPrice.
- Putting it all together Here's how you'd actually use this class from a runnable job in D365 F&O:
static void JobCallHelper(Args _args)
{
SalesOrderHelper helper = new SalesOrderHelper();
real total;
helper.init("US-001", 10, 25.50);
if (helper.validate())
{
total = helper.calcTotal();
info(strFmt("Total: %1", total));
}
}
Step by step: new SalesOrderHelper() creates an object from the blueprint. helper.init(...) fills in its fields. helper.validate() and helper.calcTotal() call its methods to check and use that data. This pattern — declare a class, instantiate an object, call its methods — is the backbone of nearly every customization you'll write in F&O.
Key takeaways
Variables are typed storage — always declare the type before the name.
A class groups fields (data) and methods (behavior) into one reusable blueprint.
An object is a live instance of a class, created with new.
Methods are how you read, change, and validate an object's data.
Next up (Day 2): how X++ organizes persistent data — tables, extended data types, and base enums.

Top comments (0)