Optional parameters in C# and X++


In the upcoming 4.0 version of C# the language now supports optional parameters – just like X++. The following is a valid method declaration in both languages:


public void foo(int parameter1, int parameter2 = 0, int parameter3 = 100)
{
}

There are a few differences between the languages with regards to optional parameters:


Named parameters


In X++ you can only omit optional parameters starting from the last parameter. C# makes it possible to omit any optional parameter. For example:


foo(5, parameter3: 1000)

will call foo(5, 0, 1000).


prmIsDefault


C# doesn’t provide a way to determine, if a parameter was omitted by the caller, or the caller passed in a value identical to the default value. In X++ the prmIsDefault() method can be used to determine this. However, the use cases for this method are rare – and often fragile. For example, consider this X++ class:


class BaseClass
{
    int value;
    public void init(int _value = 0)
    {
        if (prmIsDefault(value))
        {
            value = /* some complex calculation */
        }
        else
        {
            value = _value;
        }
    }
}
Now someone comes along and extends the class:
class MyClass extends BaseClass
{
    str myStr;
    public void init(int _value = 0)
    {
        myStr = 'foo';
        super(_value);
    }
}
Can you see the problem? This following code will never call the complex calculation (which probably was the intention):
MyClass myClass = new MyClass();
To solve the problem MyClass needs to be implemented as:
class MyClass extends BaseClass
{
    str myStr;
    public void init(int _value = 0)
    {
        myStr = 'foo';
        if (prmIsDefault(_value))
            super();
        else
            super(_value);
    }
}

Which really is terrible, as the implementation of the derived class depends on the implementation of the base class. This is bound to break eventually. Add a few more optional parameters and a few more levels of depth in the class hierarchy, and you'll have a real nightmare. My recommendation is to only use prmIsDefault() in private and final methods - as they can't be overridden. In C# you can easy live without this method, as you can achieve the same in a more robust manner using method overloading:


class BaseClass
{
    int value;
    public void init()
    {
        int _value = /* some complex calculation */
        this.init(_value);
    }
    public void init(int _value)
    {
        value = _value;
    }
}
<humor>It is a good thing we solved the dangling semicolon issue – otherwise it would haunt the C# community in a not too distant future.</humor>

Comments (3)

  1. Andrés del Campo says:

    I think X++ could gain a lot by fully supporting optinal parameters as in C#. I have seen many methods, typically the "new" methods for instantiating classes, that might receive easily 5 to 15 parameters in which most of them are defaulted. I agree that having so many parameters is discouraged as a general best practice, but there are legitimate scenarios and those methods are a reality in AX, especially in unit tests for entity creation. Having the possibility of just passing one or two of them in any order and having the rest defaulted would simplify the coding, reduce the potential errors by reducing the amount of -relevant- parameters needed, increase code clarity and semantic focus, etc. I have seen propositions of other developers to start adopting coding patterns that artifically mimicked that, which would not be needed if the language provided it out of the box.

    I am thinking about potential calls like:

    createProdOrder(Item: item1, Qty: 5, BOM: bom1);

    where the method might allow configuring 10-20 more other settings beyond default values -and assuming that we could introduce parameter 20 without introducing the 19 parameters before it…

  2. Sebastian says:

    Please not that if you have a method, say:

    void foo(int _value= 0)

    {

          if(prmIsDefault(_value))

                 info('Yes');

          else

                 info('No');

    }

    while called:

    foo(); //returns Yes

    foo(0); //returns No

    so this method does not really checks if the argument value is sames as default but checks if programmer called the method with or without passed argument.

  3. Waldemar Pross says:

    Thank You for this information!

Skip to main content