‘is’ and ‘as’ operators with .NET types

I recently ran into an unfortunate limitation of .NET Interop from X++ (in D365FO).
I wanted to check if an X++ object is of a given type, nevertheless the type used for the variable declaration was a .NET interface. Here is an example:

using Microsoft.Dynamics.ApplicationSuite.FinancialManagement.Currency.Framework;
void demo(IExchangeRateProvider _provider)
    if (_provider is ExchangeRateProviderCBOE) {}

Exchange rate providers are X++ classing implementing IExchangeRateProvider interface and I wanted to check if the object I received was a particular provider (namely ExchangeRateProviderCBOE class or its child). Unfortunately this ended up with a compilation error:

The operand on the left side of the ‘is’ or ‘as’ operator must be a table, class, or form.

As I tested, neither managed interfaces nor managed classes (such as System.Object) can be used on the left side of ‘is’ and ‘as’ operators.

I solved the problem by using Type.IsAssignableFrom() method. Simply using the ‘is’ operator would be nicer, but this does the job too.

void demo(IExchangeRateProvider _provider)
    System.Object providerObj = _provider;
    if (providerObj.GetType().IsAssignableFrom(new ExchangeRateProviderCBOE().GetType())) {}

Note that the problem is only with the left side of the operators, e.g. when you want to check whether a managed type is this or that. Using the ‘is’ operator to check if an instance of an X++ class implements a managed interface works without problems.

Object obj = new ExchangeRateProviderCBOE();
if (obj is IExchangeRateProvider) {}


    • Oops

      AnyType providerObj = _provider;
      if (providerObj is ExchangeRateProviderCBOE) {

      For ElectronicReporting we added ERCast class just to make it easier:

      if (ERCast::asObject(providerObj) is ExchangeRateProviderCBOE) {

    • Good idea! Using anytype does work (the correct syntax is if (providerObj is new ExchangeRateProviderCBOE)).
      I don’t see the point in using ERCast::asObject(), but ERCast::asAny() indeed makes things simpler, since we don’t have to declare any anytype variable. The downside is taking dependency on the ER module; it would be nice to have such things in the platform or a general-purpose library.
      By the way, there are already people like Peter Villadsen involved and it seems that X++ compiler will be extended to support this scenario. 🙂

  1. ERCast::asObject is for cases when one need to cast CLR interface to X++ object like

    void myCode(IDisposable _x)
    if (_x is MyXppClass) // does not compile
    if (ERCast::asObject(_x) is MyXppClass) // compiles

    Maybe it is fixed already but did not work in 7.3

Leave a Reply

Your email address will not be published. Required fields are marked *