0

I have the following method which compiles:

    private void onModifiedFilter(FormControl sender)
    {
        FormDataSource mainAccount_ds = sender.formRun()
            .dataSource(formDataSourceStr(MainAccount, MainAccount));
        mainAccount_ds.executeQuery();
    }

As I have no other use for mainAccount_ds, I would like to inline the value and simplify the code to:

    private void onModifiedFilter(FormControl sender)
    {
        sender.formRun()
            .dataSource(formDataSourceStr(MainAccount, MainAccount))
            .executeQuery();
    }

However, this fails to compile with:

Severity Code Description Project File Line Suppression State Error ClassDoesNotContainMethod: Class 'FormObjectSet' does not contain a definition for method 'executeQuery' and no extension method 'executeQuery' accepting a first argument of type 'FormObjectSet' is found on any extension class. Packt_MainAccountExtension (ISV) [ExpenseManagement] C:\AOSService\PackagesLocalDirectory\Bin\XppSource\ExpenseManagement\AxClass_Packt_MainAccountForm_Extension.xpp 18

  • How/why does capturing mainAccount_ds alter the ability for this method to compile?
  • Are there other ways I can express this without the unnecessary data capture?
  • When else in D365 should I expect some magic where I will need to capture a value in order to make use of it, rather than directly invoking a method upon an uncaptured return value?
FH-Inway
  • 4,432
  • 1
  • 20
  • 37
Brian Kessler
  • 2,187
  • 6
  • 28
  • 58

1 Answers1

1

To answer your main question: Because the compiler cannot determine the correct downcast type from the return value of the dataSource method.

To answer your additional questions:

  • "How/why does capturing mainAccount_ds alter the ability for this method to compile?"

The addition of the mainAccount_ds variable tells the compiler what type of the return value of the dataSource method is expected at run time. Note that the executeQuery method is only defined in the FormDataSource class, but not in the FormObjectSet parent class, which is the type of the return value of the dataSource method.

  • "Are there other ways I can express this without the unnecessary data capture?"

I don't think so. While there is an as operator to do explicit downcasts, I haven't found a way to use it inside a chained method call expression.

  • "When else in D365 should I expect some magic where I will need to capture a value in order to make use of it, rather than directly invoking a method upon an uncaptured return value?"

I hope the other answers cleared up that no magic is happening here. The compiler correctly prevents you in this case from an undefined downcast.

In addition, you might want to read up on casting in . Casting and Expression operators are a good place to start.

FH-Inway
  • 4,432
  • 1
  • 20
  • 37
  • Cheers for the response. If I understand correctly, in X++, when I capture a value the system will implicitly downcast without my needing to tell the system to do something like `FormDataSource mainAccount_ds = (FormDataSource ) sender.formRun() .dataSource(formDataSourceStr(MainAccount, MainAccount));` as I might expect in some other language? (And I guess is not even a possibility to do it like `((FormDataSource ) sender.formRun() .dataSource(formDataSourceStr(MainAccount, MainAccount))) .executeQuery();` – Brian Kessler Jul 04 '21 at 22:48
  • 1
    That's a "Yes" to both assumptions/questions. Again, I recommend reading [Casting](https://learn.microsoft.com/en-us/dynamics365/fin-ops-core/dev-itpro/dev-tools/new-x-debugger-features#casting), it should make things much clearer. – FH-Inway Jul 05 '21 at 13:45