const vs. Macro in Dynamics 365 Finance & Operations
Question 22 — Why constants (and readonly) are preferred over macros for fixed values.
Interview Question
const
keyword to define fixed values? Why are constants (and readonly members) recommended
over macros, and when is each appropriate?
Model Answer (Short)
A macro (#define) performs a simple text substitution at compile
time and has no type, scope or visibility. The const keyword — same meaning as in
C# — defines a typed, scoped constant that is initialised at declaration and cannot change. X++
also supports readonly members that are set only in the declaration or constructor.
Constants are preferred because they support IntelliSense, cross-referencing, access modifiers, comments,
scope and the debugger, and they even improve compiler performance versus macros. Macros should be
limited to cases where text substitution is genuinely required.
Why Constants Beat Macros
Advantages of const over macro
- You can attach document comments to a constant; macros can't carry them.
- Constants are supported by IntelliSense; macros are not.
- Constants are cross-referenced, so you can find all usages — impossible with macros.
- Constants respect access modifiers (private/protected/public); macro visibility is undefined.
- Constants have proper scope; macros do not.
- A
constorreadonlyvalue is visible in the debugger.
const vs. readonly
const— value known at compile time, initialised at declaration, never changes.readonly— value assigned once at runtime (in the declaration or constructor), then immutable.- Use
readonlywhen the value can't be known until an object is constructed.
Prerequisites (Rule 5)
- Visual Studio with the Dynamics 365 developer tools.
- A custom model / package for your objects.
- A class or method in which to declare the constant(s).
Code Example — Macro vs. const
void constsUsage()
{
// Macro: simple text substitution, no type/scope
#define.oneNumber("AX 2012")
// const: typed, scoped, IntelliSense + cross-reference friendly
const str OneNumber = "Dynamics 365 for Operations";
info(#oneNumber);
info(OneNumber);
}
Public constants on a dedicated class
// Keep constants as public static members instead of a macro library
static class TimeConstants
{
static const public int DaysPerWeek = 7;
static const public int HoursPerDay = 24;
static const public int HoursPerWeek = TimeConstants::DaysPerWeek
* TimeConstants::HoursPerDay;
}
readonly member set in the constructor
class AbcConfig
{
readonly str identifier = "XYZ"; // set at declaration
readonly str identifier2; // set in constructor
public void new(str _identifier)
{
identifier2 = _identifier; // allowed only here
}
public void foo()
{
// identifier2 = "JP"; // ERROR: field is read only
}
}
Macro vs. const vs. readonly
| Aspect | Macro (#define) | const | readonly |
|---|---|---|---|
| Typed | No (text substitution) | Yes | Yes |
| When set | Compile time (textual) | Compile time | Runtime (once) |
| IntelliSense | No | Yes | Yes |
| Cross-reference | No | Yes | Yes |
| Visible in debugger | No | Yes | Yes |
Points the interviewer wants to hear
- A macro is text substitution;
constis a typed, scoped value. - Constants support IntelliSense, cross-reference, access modifiers and the debugger.
- Prefer public static const members over a macro library.
- Use
readonlywhen the value is set once at runtime (constructor). - Constants can even improve compiler performance over macros.
Likely Follow-up Questions
- Why can't you attach a comment or find references to a macro?
- When is a macro still the right choice?
- What is the difference between
constandreadonly? - Where should shared constants live in a solution?
Key Takeaway
Prefer const (and readonly for runtime-set values)
over macros: constants are typed, scoped, discoverable via IntelliSense and cross-reference,
visible in the debugger, and even faster to compile. Reserve macros for genuine text substitution.