With BC25, we have been given a new keyword in AL, “this”. It is mainly introduced for use with codeunits, but it also exists outside codeunits. Check out the video on this!

In this video, Erik explores the this keyword that was introduced in Business Central 25 (AL runtime 14.0). He walks through what this means, how it differs from the existing CurrPage/CurrReport/CurrXMLport constructs, and where it works — and where it doesn’t yet.
What Is the this Keyword?
With BC25, AL got a new keyword: this. In programming language terms, a keyword is one of the fundamental pieces that makes up the construction of a language. The this keyword is well-known in many other object-oriented languages — it’s a self-reference. When you’re inside an object, this lets you either pass yourself as a parameter to something else, or distinguish between a local variable and a property on the object you’re in.
But Wait — Don’t We Already Have CurrPage and CurrReport?
You might be thinking: “Hang on Erik, we’ve had this concept in Business Central, NAV, and AL for decades — isn’t this just the same as CurrPage, CurrReport, or CurrXMLport?”
It kind of is, but it’s not. Let’s dig into the differences.
Codeunits as Objects: The Primary Use Case
To understand why this matters, we need to look at how codeunits are evolving in AL. Consider the pattern used by the Email module in Business Central. You have the Email codeunit, which is a library of code — old-school style, like codeunits have been since the early days. Then you have the Email Message codeunit, which is more like an object — it holds data. You create it, set recipients, subjects, bodies, add attachments, etc.
This distinction is important: some codeunits are libraries of code, while others are objects with state. When a codeunit acts as an object, you might need to pass yourself to another codeunit. Before BC25, there was no way to do this — there was no CurrCodeunit construct.
Now, with this, you can. Here’s the core example:
codeunit 50100 test
{
trigger OnRun()
var
Verify: Codeunit "Verify Test";
begin
Verify.Verify(this);
end;
}
codeunit 50101 "Verify Test"
{
procedure Verify(test: Codeunit Test)
begin
// Now we have a reference to the calling codeunit
end;
}
This is something we could never do before. The this keyword passes the codeunit instance itself as a parameter to the Verify procedure. That’s the primary motivation for introducing this.
this vs. CurrPage on Pages
On pages, things get interesting. You can use this, and you can still use CurrPage — but they’re not the same thing.
page 50100 thistest
{
trigger OnOpenPage()
var
Verify: Codeunit "Verify Test";
begin
//Verify.VerifyPage(this); // This doesn't compile!
this.CurrPage.Update(); // This works
this.Update(); // This also works
end;
}
CurrPage is a magic pseudo-construct — it’s not actually a Page type. You can see this clearly when you try to pass it as a parameter:
procedure VerifyPage(p: Page thistest)
begin
end;
If you try to call Verify.VerifyPage(CurrPage), you get: “cannot convert from CurrPage thistest to Page thistest”. CurrPage is a different construct — it gives you access to functions on the page (like Update()), but it’s not the page object itself.
Interestingly, at the time of recording, passing this as a page parameter also produced a similar conversion error — something Erik discovered live during the video and acknowledged as a potential compiler bug or limitation to be resolved.
this on Reports — It Works!
On reports, this works as you’d expect for passing self-references:
report 50100 thisreport
{
trigger OnInitReport()
var
Verify: Codeunit "Verify Test";
begin
Verify.VerifyReport(this);
end;
}
procedure VerifyReport(r: Report thisreport)
begin
end;
This compiles and works without issues.
this on XMLports — Partial Support
XMLports also support this, but with some inconsistencies. You can pass this to another codeunit and access some built-in functions, but not all:
xmlport 50100 xmlthis
{
schema
{
textelement("data-set-c_Localidad")
{
tableelement("SAT Locality"; "SAT Locality")
{
XmlName = 'Localidad';
fieldelement(Code; "SAT Locality".Code) { }
fieldelement(State; "SAT Locality".State) { }
fieldelement(Descripcion; "SAT Locality".Description) { }
trigger OnAfterGetRecord()
begin
this.break(); // Does NOT compile!
end;
}
}
}
trigger OnInitXmlPort()
var
Verify: Codeunit "Verify Test";
begin
this.currXMLport.Break(); // Works
Verify.VerifyXmlport(this); // Works
end;
}
So this.currXMLport.Break() works, and passing this as a parameter works, but calling this.Break() directly does not — even from a trigger where Break() would be valid. Erik notes this is an area where this likely needs further improvement.
The Complete Source Code
Here’s the verify codeunit that ties everything together:
codeunit 50101 "Verify Test"
{
procedure Verify(test: Codeunit Test)
begin
end;
procedure VerifyPage(p: Page thistest)
begin
end;
procedure VerifyReport(r: Report thisreport)
begin
end;
procedure VerifyXmlport(p: XmlPort xmlthis)
begin
end;
}
Key Differences: this vs. Curr*
CurrPage/CurrReport/CurrXMLport— These are pseudo-constructs that give you access to specific functions on the current object (likeUpdate(),Break(), etc.), but they are not the object itself and cannot be passed as typed parameters.this— This is the actual object reference. Its primary purpose is to allow you to pass the current object instance to another procedure, which is especially useful for codeunits used as objects.- Codeunits are where
thisshines most — there was noCurrCodeunitbefore, so this fills a real gap. - Pages, reports, and XMLports have varying levels of support for
this, with some inconsistencies that may be improved in future releases.
Summary
The this keyword in BC25 is primarily about enabling codeunits to act more like true objects — specifically, the ability to pass yourself as a parameter to other procedures. While the Curr* constructs have existed for decades and give access to object-specific functions, they are not actual object references. The this keyword fills that gap. As of the initial release, support varies across object types — it works cleanly on codeunits and reports, but has some rough edges on pages and XMLports that will likely be polished in future versions.