As you ever used the WITH clause in C/AL or AL language? There are lovers of this clause and there are developers that hate using this clause (I’m in this second category), but despite every personal opinion the WITH clause is widely used in code and also in the Microsof’s Base Application.
As announced at the Dynamics 365 Business Central Virtual Event, Microsoft is continuously evolving the platform and their apps (today and in the future) and they need to be able to upgrade tenants smoothly while trying to not break our extensions.
The WITH clause can help you on writing a more readable code in certain situations (I don’t think so but that was the goal) but it creates a lot of un-efficiency related to code compilation. For avoiding this, Microsoft is planning to making the WITH clause obsolete and you should start forgot it (please don’t use it anymore!) and start fixing your apps accordingly.
When using WITH, in AL (or C/AL too) there are two types of usage: explicit WITH and implicit WITH.
Explicit WITH is something like in the following example:
Here I have a codeunit with a ProcessCustomer method that uses WITH to reference the Customer record. The procedure calls a local method called IsReady to determine if the Customer record can be inserted into the database.
What happens now if another extension (or Microsoft itself) will add a new method called IsReady in the Customer table? Something like the following:
The problem here is related to symbols lookup. To resolve symbols, the compiler checks the following scopes (in the following order):
- “With” scope: Customer and Customer extension members, Record class members
- Method scope: Parameters and variables
- Object scope: global variables and methods, fields, base class members
- Global scope: enums, built-in methods and classes
In this way, your code here can have an unpredictable result (the IsReady() method declared in the tableextension wins and brokes your code because you can have totally different results than what you want to achieve in your local IsReady() method).
And if (for example) the IsReady() method declared in the tableextension requires a parameter, your code will not compile anymore and your extension is totally broken (you have a compilation error now):
This is the reason while Microsoft in the future AL language extension will signal you a warning in code if you’re using the WITH clause:
and fortunately you will have code actions for fixing these problems:
taht when clicked will transform your code as follows:
While fixing the explicit WITH could be quite easy, the implicit WITH is instead more difficult to catch and it’s something like in the following example. Imagine that I have a codeunit that works on the Customer table:
Here the implicit WITH could be fixed by prefixing Rec. and you can use AL code actions to do that:
If I click on the code action for fixing the implicit WITH, you can see that the code is fixed by appending Rec. to the methods, but the IsReady() method that I want to use here is not prefixed (because it’s declared locally):
And if someone (a third-party extension or Microsoft itself) will add an IsReady() method to the Customer table in the future? For solving this problem, the new code action for resolving the implicit with will add also a pragma declaration for the compiler (#pragma implicitwith disable):
In this way the compiler will not resolve the IsReady() method by going to the previously explained chain and it will always found the local declaration.
The usage of implicit WITH must be fixed also on pages, where you have a field reference. All fields on a page must be fixed with Rec.YourField:
and you will have code actions for fixing this quickly:
You can also disable the Microsoft warnings related to the explicit (AL0606) or implicit (AL0604) WITH usage by using the following directive in your code (.al file):
#pragma warning disable AL0604,AL0606
And you can also disable these warnings globally by adding this declaration in your app.json file:
“suppressWarnings”: [ “AL0604”, “AL0606”]
but personally this is not what I would recommend you to do.
Common questions that you can have about this:
- Will I receive a warning starting from tomorrow about WITH usage? No, this is planned for the Wave 2 2020 release (5 months later on)
- Should I start fixing my apps now? I think the answer is yes, start avoiding the WITH usage from today and start fixing the implicit with from today if you can.
- When the WITH usage will be transformed from a warning to an error? At least one year later, so Wave 2 2021 at least.
Please don’t wait too much and start fixing your apps by avoiding the WITH usage starting from today.