This! is a video on This! in AL

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!

https://youtu.be/707axQmQsSM

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 (like Update(), 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 this shines most — there was no CurrCodeunit before, 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.