Expression Operators: Is and As for Inheritance

Applies To: Microsoft Dynamics AX 2012 R3, Microsoft Dynamics AX 2012 R2, Microsoft Dynamics AX 2012 Feature Pack, Microsoft Dynamics AX 2012

In Microsoft Dynamics AX, the X++ language provides the as and is expression operators to control downcast assignments. Downcast assignments involve class or table inheritance.

Note

For information about the terminology of inheritance, see Inheritance Terminology.

Assignment statements that implicitly downcast can cause errors that are hard for the programmer to predict or diagnose. You can use the as keyword to make your downcasts explicit. You can use the is keyword to test whether a downcast is valid at run time.

As Keyword

You can use the as keyword for assignments that downcast from a base class variable to a derived class variable. The as keyword tells other programmers and the compiler that you believe the downcast will be valid during run time.

Gg843452.collapse_all(en-us,AX.60).gifAs Keyword at Compile Time

Starting in Microsoft Dynamics AX 2012 or in a release to follow, the X++ compiler reports an error for downcast assignment statements that lack the as keyword.

Gg843452.collapse_all(en-us,AX.60).gifAs Keyword at Run Time

At run time, the as keyword causes the downcast assignment statement to assign null if the downcast is invalid.

Gg843452.collapse_all(en-us,AX.60).gifCode Example for the As Keyword

In the following code example, the DerivedClass class extends the BaseClass class. The code example contains two valid assignments between its basec and derivedc variables. The upcast assignment to basec does not need the as keyword, but the downcast assignment to derivedc does need the as keyword. The following code would compile and run without errors.

    static void AsTestJob33(Args _args)
    {
        // DerivedClass extends BaseClass.
        BaseClass basec; 
        DerivedClass derivedc;
    
        // BottomClass extends DerivedClass.
        BottomClass bottomc;
    
        derivedc = new DerivedClass();
    
        // AS is not needed for an upcast assignment like this.
        basec = derivedc;
    
        // AS is needed for a downcast assignment like this.
        derivedc = basec as DerivedClass;
    
        bottomc = new BottomClass();
        // AS causes this invalid downcast to assign null.
        bottomc = basec as DerivedClass;
    }

Is Keyword

The is keyword ascertains whether an object is a subtype of a specified class. The is expression returns true if the object is a subtype of the class, or if the object is the same type as the class.

Gg843452.collapse_all(en-us,AX.60).gifIs Keyword at Compile Time

The X++ compiler reports an error if an is keyword expression compares two types where neither is a subtype of the other, and they are not of the same type. The compiler reports a similar error for any plain assignment statement between two types where neither is a subtype of the other, and they are not of the same type.

Gg843452.collapse_all(en-us,AX.60).gifIs Keyword at Run Time

At run time the type of variable that references the underlying object is irrelevant to the is keyword. The is keyword causes the system to check the object that the variable references, not the declared type of the variable that references the object.

Gg843452.collapse_all(en-us,AX.60).gifCode Examples for the Is Keyword

The following code examples illustrate the conditions that control whether an is expression returns true or false. The code examples rely on the fact that the Form class and the Query class both extend the TreeNode class.

Code example

Explanation

Form myForm = new Form();
info(strFmt("%1", (myForm is Query)));

The X++ compiler issues an error.

The compiler ascertains that the Form class and the Query class are not part of the same inheritance hierarchy. Both the Form class and the Query extends the TreeNode class, but neither Form nor Query is a subtype of the other.

TreeNode myTreeNode = new TreeNode();
info(strFmt("%1", (myTreeNode is Form)));

The Infolog displays 0 during run time, where 0 means false.

No supertype object can be considered to also be of its subtype class.

Form myForm;
info(strFmt("%1", (myForm is Form)));

The Infolog displays 0 during run time, where 0 means false.

A null reference causes the is expression to return false.

Form myForm = new Form();
info(strFmt("%1", (myForm is Form)));

The Infolog displays 1 during run time, where 1 means true.

An object is an instance of its own class type.

Form myForm = new Form();
info(strFmt("%1", (myForm is TreeNode)));

The Infolog displays 1 during run time, where 1 means true.

Every subtype is also of its supertype.

Form myForm = new Form();
TreeNode myTreeNode;
myTreeNode = myForm; // Upcast.
info(strFmt("%1", (myTreeNode is Form)));

The Infolog displays 1 during run time, where 1 means true.

The type of the underlying object is what matters in the is expression, not the type of the variable that references the object.

Using Is and As Keywords Together

This is keyword is often used to safely test whether the as keyword will work.

Gg843452.collapse_all(en-us,AX.60).gifCode Example

The following code example contains a common use of the is keyword. The as keyword is used after the is keyword verifies that the as keyword will the object. The is and as keywords are uppercase to make them more visible in this example.

    static void IsKeywordJob46(Args _args) // X++
    {
        DerivedClass derivedc;
        BaseClass basec;
    
        basec = new DerivedClass();  // An upcast.
        if (basec IS DerivedClass)
        {
            info("Test 1: (basec IS DerivedClass) is true. Good.");
            derivedc = basec AS DerivedClass;
        }
    
        basec = new BaseClass();
        if (!(basec IS DerivedClass))
        {
            info("Test 2: (!(basec IS DerivedClass) is true. Good."));
        }
    }

Output to the Infolog

Test 1: (basec IS DerivedClass) is true. Good.

Test 2: (!(basec IS DerivedClass)) is true. Good.

Object Class is a Special Case

The Object class can appear as a special case in inheritance functionality. The X++ compiler has special logic to bypass type checking for assignments to and from variables that are declared of type Object.

Note

You could misinterpret some X++ statements if you are unaware of this special case.

Some classes inherit from the Object class, some inherit from another class, and some do not inherit from any class. The Dialog class does not inherit from any class, yet the assignment and call statements in the following code example all work.

    static void ObjectIsAsJob4(Args _args)
    {
        Bank bank4;
        Object obj2;
        Dialog dlog3 = new Dialog("Test 4.");
    
        obj2 = dlog3;  // The assignment does work.
        obj2.run(false);  // The call causes the dialog to display.
        info("Test 4a is finished.");
        ...
    }

The assignment would fail at compile time if it had been bank4 = dlog3;, because the Bank and Dialog classes have no inheritance relationship to each other.

The X++ compiler performs only one small check on assignments to a variable that is declared of the Object class. The compiler checks to make sure that the item being assigned to the Object variable is an instance of a class.

The compiler does not allow an instance of a table buffer to be assigned to the Object variable. Also, the compiler does not allow primitive data types, such as int or str, to be assigned to the Object variable.

Gg843452.collapse_all(en-us,AX.60).gifRoot Items in Table Inheritance

All tables inherit directly from the Common system table, unless they explicitly inherit from a different table. The Common table cannot be instantiated. The Common table does not exist in the underlying physical database. The Common table inherits from the xRecord class, but only in a special way that is not appropriate for the is keyword or the as keyword.

As Keyword and Tables

When the as keyword is used to perform an invalid downcast among tables, the target variable references an unusable non-null entity. Any attempt to dereference the target variable will cause an error that stops the X++ program.

Is and As Keywords and Extended Data Types

Each extended data type has an Extends property. The style of inheritance that is controlled by this property differs from the style of inheritance that the is and as keywords are designed for.

More Information about Inheritance

For information about the extends keyword for inheritance between classes, see X++ Keywords and X++, C# Comparison: Object Oriented Programming.

For information about inheritance between tables, see Table Inheritance Overview.

See also

Operators

Inheritance Terminology

SysDictClass::is Method

SysDictClass::as Method

SysDictClass::isEqualOrSuperclass Method

SysDictClass::isSuperclass Method

Announcements: New book: "Inside Microsoft Dynamics AX 2012 R3" now available. Get your copy at the MS Press Store.