delphiproceduretstringlist

TStringList is not passing value


So i have a procedure, that is getting the list of dom nodes.

procedure TmainForm.getNodeListByClass(className:string; outputList:TStringList);
var
  foundNode:TDomTreeNode;
  foundNodesList:TStringlist;
begin
foundNodesList:=Tstringlist.Create;

foundNode:=nodeFindNodeByClassName(DomTree.RootNode,className);
if Assigned(foundNode) then
    getNodeList(foundNode,foundNodesList);

outputList:=foundNodesList;
freeandnil(foundNodesList);
end;

And a procedure that is using it

procedure TmainForm.getByXpathBtnClick(Sender: TObject);
var
  temp:TStringlist;

begin
temp:=TStringlist.Create;

temp.Add('testval');

getNodeListByClass('table_input',temp);
memo1.Lines:=temp;

getNodeListByClass('left iteminfo',temp);
dbgForm.memo1.Lines:=temp;

getNodeListByClass('left',temp);
dbgForm.memo2.Lines:=temp;

freeandnil(temp);
end;

And i really don't understand, why it wouldn't work, result of first procedure is always empty. I found out, that when the first procedure is executing, "foundNodesList" have the correct list, and setting it to "outputList" is working too, but as soon as its returning to the second procedure (in "temp" list) its just empty. So its clearing old data from "test" ('testval' what i am writing in the beginning), but not adding the result from the first one.

Could someone point me in the right direction?


Solution

  • The problem is here

    outputList := foundNodesList;
    FreeAndNil(foundNodesList);
    

    The assignment is a reference assignment. I think that you are expecting the content of foundNodesList to be transferred into outputList. But what happens is that you end up with two variables referring to the same instance.

    Your code can be fixed very easily. You do not need a temporary string list, you can simply populate the string list passed into the method.

    procedure TmainForm.getNodeListByClass(className: string; outputList: TStringList);
    var
      foundNode: TDomTreeNode;
    begin
      outputList.Clear;
      foundNode := nodeFindNodeByClassName(DomTree.RootNode, className);
      if Assigned(foundNode) then
        getNodeList(foundNode, outputList);
    end;
    

    Note that in the other function when you write

    memo1.Lines := temp;
    

    this works a little differently. The Lines property of a TMemo has a property setter that copies the right hand side, rather than taking a reference. Your code that performs assignment to Lines is therefore correct.