D365O. X++ objects equality.

balance

There are two different kinds of equality: equality by reference and equality by value. I’m not going to explain these basic concepts here, because you can find tons of information in the web, today I want to show how you can implement value based comparison in X++.

By default AX uses reference check. In previous versions we could override equal method of the Object class to implement value based comparison, however, we have to explicitly derive new class from Object, because it was not derived by default and equal was not called by AX (as far as I know). For example, if you wanted to use value equality with collections, like set, you had to workaround using map where key is combination of fields and value is object itself.

With new version of AX we moved to .NET world where X++ is almost a first class citizen. Why almost?  There are bunch of limitations and not implemented features like generics, but we slowly getting there.

Let’s get back to value equality. Now, each class is derived from System.Object. System.Object has Equals and GetHashCode methods used to check equality that we can override. Again, there are lots of info in the web about these two methods and guidelines how to override them, so I’ll jump straight into the example.

I have a new class with two public fields:

class MyClass
{
    public int a;
    public int b;
}

In my test job, I want to store instances of MyClass in a set. Set should contain only instances with unique combination of a and b values.

public static void main(Args _args)
{
    MyClass myClass1 = new MyClass();
    myClass1.a = 5;
    myClass1.b = 10;

    MyClass myClass2 = new MyClass();
    myClass2.a = 5;
    myClass2.b = 10;

    Set set = new Set(Types::Class);

    set.add(myClass1);
    set.add(myClass2);

    info(int2Str(set.elements()));
}

As we already know, AX will add 2 elements into the set because it always performs reference check by default.

Let’s override Equals and GetHashCode using MSDN guidelines

public int GetHashCode()
{
    return this.a ^ this.b;
}

public boolean Equals(System.Object _obj)
{
    if (_obj == null)
    {
        return false;
    }

    if (System.Object::ReferenceEquals(this, _obj))
    {
        return true;
    }

    if (!this.GetType().Equals(_obj.GetType()))
    {
        return false;
    }

    MyClass compareTo = _obj;

    if (compareTo.a == this.a && compareTo.b == this.b)
    {
        return true;
    }
    else
    {
        return false;
    }
}

It’s just an example how “standard” features from .NET could be used in X++. Moving forward, you can expand this example implementing IComparable interface, so new class could be added to any standard .NET collection and be sorted! But it’s a topic for another blog.

Advertisements