Dynamics Ax: X++ what’s new

Hi All!

As you’ve probably already heard the new major release of Dynamics Ax is out and it’s called Microsoft Dynamics Ax! I have been to the Ax7 technical preview conference so I’ve already prepared some content for you and now that the release is official I can share it all. Dynamics Ax comes along with a whole bunch of new goodies and the new compiler being the biggest one. This allowed Microsoft to implement a whole bunch of new keywords in our beloved X++ language.

This keyword for variables

We already had the this keyword for calling methods, but now we can also use it to assign values to variables or pass them.

public class TestClass
{
    private str myVar = "This is a test";
 
    public void start(str _myVar)
    {
        this.myVar = _myVar;
        this.test(this.myVar);
    }
 
    public void test(str    _myVar)
    {
        info(_myVar);
    }
}

Static constructors and fields

You all probably know this but a static variable is a variable shared among all instances of a class. And what do all we pattern loving developers think? Exactly the singleton pattern is finally possible without dirty caching tricks!

public class StaticVariables
{
    private static StaticVariables myInstance = null;
 
    public static StaticVariables construct()
    {
        if(myInstance == null)
        {
            myInstance = new StaticVariables();
        }
 
        return myInstance;
    }
 
}

The static constructor is called TypeNew()

  • These are automatically called before the first use of a class.
  • These are called once for each type and each session.

Var variables and declaration

Declaring a variable as a var type (implicitly typing) will let the compiler decide which type it is, therefor you don’t have to. When a var variable is assigned to a type this cannot be changed anymore.

var i = 1; // implicitly typed
int i = 1; //explicitly typed

And from now on you can also declare anywhere!

for(int i = 0; i <= 10; i++)
{
    int current = i;
    info(strFmt("%1", i));
}

Const/readonly variables

  • Const: This is a constant and can only be assigned a value when declaring it.
  • readonly: The value of this variable can be changed at runtime but only through a constructor.
public class ReadOnlyKeywordTest
{
    readonly str myVar = "This is a test";
 
    public void new(str _myVar)
    {
        this.myVar = _myVar;
    }
 
    public void test()
    {
        // This does not compile
        myVar = "this code fails";
    }
 
}

Public / protected / private access modifier for variables

Data encapsulation can now implemented decent because as in C# we can declare our variables public, protected or private. This makes code more robust when implemented well.

  • public: Access is not restricted.
  • protected: Access is limited to the containing class or types derived from the containing class.
  • private: Access is limited to the containing type.

The difference with C# is that the default modifier still is protected, because changing it to private would break too much existing application code.

Finally in try/catch statements

Finally! A way of executing code when either the entire try statement has finished or a handled exception has occurred.

public void run()
{
    try
    {
        // Run business logic
    }
    catch(Exception::Error)
    {
        // Handle the exception 
        // Example: propagate a decent error message to the user
    }
    finally
    {
        // Example: Cleanup allocated resources
    }
}

Typed exceptions

And exception handling even get’s better! Because now we can handle any exception that extends from System.Exception. Which is a big leap forward when using the .NET framework.

System.NullReferenceException   nullReferenceException;
 
try
{
    // Run business logic
}
catch(nullReferenceException)
{
    // Handle the exception 
}

Using keyword

No more worries about memory leaks when consuming unmanaged resources because now you can use the using keyword for objects that implement IDisposable.

using(var dataSet = new System.Data.DataSet())
{
    // Do stuff with it
}

Extension methods

What if there was a way to add methods to an object without modifying it in your customization layer? Well now there is, it’s called extension methods and the principle is the same as in C#.

public static class BLOGCustTable_Extension
{
    static const str prefix = 'DEMO';
 
    public static str blogPrefixedCustAccount(CustTable custTable)
    {
        return strFmt("%1-%2", prefix, custTable.AccountNum);
    }
 
    public static void main(Args _args)
    {
        CustTable custTable;
 
        select firstonly custTable;
 
        info(custTable.blogPrefixedCustAccount());
    }
 
}

Some reminders when using this:

  • Use these in a static class.
  • The name of the class must have the suffix “_Extension”.
  • The method is public.

Declarative enventing: with pre and post events

In 2012 we already had eventing, but one minor flaw most developers had issues with was that you had to change the object you where subscribing to. Since we run fully in IL it is possible to subscribe to an event without modifying the sender object.

For instance the DirPartyTable has a delegate method dirPartyDeleted.

public class DirPartyTable extends common
{
    delegate void dirPartyDeleted(DirPartyTable dirPartyTable)
    {
    }
}
 
public class BLOGEventing
{
    [SubscribesTo(tablestr(DirPartyTable), delegateStr(DirPartyTable, dirPartyDeleted))]
    public static void handleDirPartyTableDelete(DirPartyTable partyTable)
    {
        info(strFmt("Deleting : %1",partyTable.PartyNumber));
    }
 
}

 

Using clauses

Remember the days when you want to use a .NET library and you always had to write the entire namespace? Well those days are over.

using System.IO;
 
public class BLOGUsing
{
    public void testDirectory()
    {
        if(Directory::Exists("C:\Temp") == true)
        {
            info("ok");
        }
    }
 
}

Enjoy your coding with all the new goodies! 🙂

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.