Options

DotNet-Variables always passed as Call-By-Reference parameter?

okioki Member Posts: 46
Hello,

for a special Xml-node iteration, I used a subfunction and the firstchild/nextsibling methods.
The text export at the end of this question shows a reduced example of the usage.

If you run it, the result is as follows:

ta6twsz9nadt.png

For me it is not clear why the "CallByVal" function in Part 1 behaves the way it does.
I expected a result for Part 1 equal to Part 2.

The "CallByRef" shows its results as expected

In this case there are three possible types of function parameter passing:
a) The node itself is pushed onto the stack - no change outside of the function possible
b) The pointer to the node is pushed onto the stack - no change outside of the function possible
c) The reference (pointer) to the pointer to the node is pushed onto the stack - the pointer to the node can be changed to affect the variable outside of the function

Only in case c) it's possible that the dotnet variable in the caller will be changed.

Is it so that the case c) for DotNet variables (=CallByReference) is always used?
Is this an intended feature or rather a bug?

Oki
OBJECT Codeunit 50010 TEST DOTNET FCT PARAMS
{
  OBJECT-PROPERTIES
  {
    Date=19.02.18;
    Time=12:00:00;
    Modified=Yes;
    Version List=TEST DOTNET FCT PARAMS;
  }
  PROPERTIES
  {
    OnRun=BEGIN
            StartTest;
          END;

  }
  CODE
  {

    LOCAL PROCEDURE StartTest@1000000000();
    VAR
      LXmlDoc@1000000004 : DotNet "'System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Xml.XmlDocument";
      LXmlNode@1000000002 : DotNet "'System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Xml.XmlNode";
      LXmlNode1@1000000005 : DotNet "'System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Xml.XmlNode";
      LXmlNode2@1000000001 : DotNet "'System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Xml.XmlNode";
      LXmlNode3@1000000000 : DotNet "'System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Xml.XmlNode";
      LXml@1000000003 : Text;
      LTxt@1000000006 : Text;
    BEGIN
      LXml :=
      '<test>'+
      '  <item>a1$</item>'+
      '  <item>b2€</item>'+
      '  <item>c3µ</item>'+
      '</test>';
      LXmlDoc := LXmlDoc.XmlDocument;

      // 'CallByValue PART 1'
      LXmlDoc.LoadXml(LXml);
      LXmlNode := LXmlDoc.SelectSingleNode('test');
      LXmlNode := LXmlNode.FirstChild;
      LTxt += CallByVal(1,1,LXmlNode); // Shows "Column 1: a,b,c,"
      LTxt += CallByVal(1,2,LXmlNode); // Shows "Column 2:
      LTxt += CallByVal(1,3,LXmlNode); // Shows "Column 3:

      // 'CallByValue PART 2'
      LXmlDoc.LoadXml(LXml);
      LXmlNode := LXmlDoc.SelectSingleNode('test');
      LXmlNode1 := LXmlNode.FirstChild;
      LXmlNode2 := LXmlNode.FirstChild;
      LXmlNode3 := LXmlNode.FirstChild;
      LTxt += CallByVal(2,1,LXmlNode1); // Shows "Column 1: a,b,c,"
      LTxt += CallByVal(2,2,LXmlNode2); // Shows "Column 2: 1,2,3,"
      LTxt += CallByVal(2,3,LXmlNode3); // Shows "Column 3: $,€,µ,"

      LTxt += '\';

      // 'CallByReference PART 1'
      LXmlDoc.LoadXml(LXml);
      LXmlNode := LXmlDoc.SelectSingleNode('test');
      LXmlNode := LXmlNode.FirstChild;
      LTxt += CallByRef(1,1,LXmlNode); // Shows "Column 1: a,b,c,"
      LTxt += CallByRef(1,2,LXmlNode); // Shows "Column 2:
      LTxt += CallByRef(1,3,LXmlNode); // Shows "Column 3:

      // 'CallByReference PART 2'
      LXmlDoc.LoadXml(LXml);
      LXmlNode := LXmlDoc.SelectSingleNode('test');
      LXmlNode1 := LXmlNode.FirstChild;
      LXmlNode2 := LXmlNode.FirstChild;
      LXmlNode3 := LXmlNode.FirstChild;
      LTxt += CallByRef(2,1,LXmlNode1); // Shows "Column 1: a,b,c,"
      LTxt += CallByRef(2,2,LXmlNode2); // Shows "Column 2: 1,2,3,"
      LTxt += CallByRef(2,3,LXmlNode3); // Shows "Column 3: $,€,µ,"

      MESSAGE(LTxt);
    END;

    LOCAL PROCEDURE CallByVal@1000000001(pPart@1000000003 : Integer;pColumn@1000000000 : Integer;pNode@1000000002 : DotNet "'System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Xml.XmlNode") : Text;
    VAR
      LTxt@1000000001 : Text;
    BEGIN
      WHILE NOT ISNULL(pNode) DO BEGIN
        LTxt += COPYSTR(pNode.InnerText,pColumn,1)+',';
        pNode := pNode.NextSibling;
      END;
      EXIT(STRSUBSTNO('CallByVal Part %1 Column %2: ',pPart,pColumn)+LTxt+'\');
    END;

    LOCAL PROCEDURE CallByRef@1000000002(pPart@1000000003 : Integer;pColumn@1000000000 : Integer;VAR pNode@1000000002 : DotNet "'System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Xml.XmlNode") : Text;
    VAR
      LTxt@1000000001 : Text;
    BEGIN
      WHILE NOT ISNULL(pNode) DO BEGIN
        LTxt += COPYSTR(pNode.InnerText,pColumn,1)+',';
        pNode := pNode.NextSibling;
      END;
      EXIT(STRSUBSTNO('CallByRef Part %1 Column %2: ',pPart,pColumn)+LTxt+'\');
    END;

    BEGIN
    {
      TEST DOTNET FUNCTION PARAMETERS
    }
    END.
  }
}

Best Answer

Answers

Sign In or Register to comment.