TStringList 没有传递值
TStringList is not passing value
所以我有一个程序,就是获取 dom 个节点的列表。
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;
以及正在使用它的程序
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;
而且我真的不明白,为什么它不起作用,第一个过程的结果总是空的。
我发现,当第一个过程正在执行时,"foundNodesList" 有正确的列表,并且将它设置为 "outputList" 也在工作,但是一旦它返回到第二个过程(在 "temp" 列表)它只是空的。
所以它从 "test" 中清除旧数据('testval' 我在开头写的内容),但不添加第一个结果。
有人能给我指出正确的方向吗?
问题就在这里
outputList := foundNodesList;
FreeAndNil(foundNodesList);
作业是参考作业。我认为您希望将 foundNodesList
的内容转移到 outputList
中。但是发生的事情是你最终得到两个引用同一个实例的变量。
您的代码很容易修复。您不需要临时字符串列表,您可以简单地填充传递给方法的字符串列表。
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;
注意在其他函数写的时候
memo1.Lines := temp;
这有点不同。 TMemo
的 Lines
属性 有一个 属性 setter 复制 右侧,而不是采用一个参考。因此,您执行分配给 Lines
的代码是正确的。
你必须明白对象是Delphi中的引用类型,并且这些引用是按值传递的。所以你的程序
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;
永远不会改变调用者的outputList
。事实上,行
outputList:=foundNodesList;
仅设置 getNodeListByClass
过程的 自己的局部变量 outputList
,它只是指向调用者字符串列表的指针的副本。因此,指针的这个副本被更改,但实际对象和调用者指向它的指针保持不变。
此外,即使情况并非如此,您的代码也会有错误,因为
freeandnil(foundNodesList);
销毁字符串列表对象 foundNodesList
,这是 outputList
指向的同一对象。因此,如果调用者能够看到 "new" outputList
(如果它是一个 var
参数),它只会看到一个悬空指针(内存损坏错误)。
你需要的是
procedure TmainForm.getNodeListByClass(const className: string; outputList: TStringList);
var
foundNode: TDomTreeNode;
foundNodesList: TStringlist;
begin
foundNodesList := TStringList.Create;
try
foundNode := nodeFindNodeByClassName(DomTree.RootNode, className);
if Assigned(foundNode) then
getNodeList(foundNode, foundNodesList);
outputList.Assign(foundNodeList);
finally
foundNodeList.Free;
end;
end;
假设您的功能按照我认为的那样进行。但这可以简化为
procedure TmainForm.getNodeListByClass(const className: string; outputList: TStringList);
var
foundNode: TDomTreeNode;
begin
outputList.Clear;
foundNode := nodeFindNodeByClassName(DomTree.RootNode, className);
if Assigned(foundNode) then
getNodeList(foundNode, outputList);
end;
(不知道你是想追加还是替换列表,你得相应调整代码。)
此外,请注意您始终必须保护您的对象,例如使用 try..finally
块。您的代码绝不能泄漏资源(例如内存),即使引发异常也不行!
所以我有一个程序,就是获取 dom 个节点的列表。
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;
以及正在使用它的程序
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;
而且我真的不明白,为什么它不起作用,第一个过程的结果总是空的。 我发现,当第一个过程正在执行时,"foundNodesList" 有正确的列表,并且将它设置为 "outputList" 也在工作,但是一旦它返回到第二个过程(在 "temp" 列表)它只是空的。 所以它从 "test" 中清除旧数据('testval' 我在开头写的内容),但不添加第一个结果。
有人能给我指出正确的方向吗?
问题就在这里
outputList := foundNodesList;
FreeAndNil(foundNodesList);
作业是参考作业。我认为您希望将 foundNodesList
的内容转移到 outputList
中。但是发生的事情是你最终得到两个引用同一个实例的变量。
您的代码很容易修复。您不需要临时字符串列表,您可以简单地填充传递给方法的字符串列表。
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;
注意在其他函数写的时候
memo1.Lines := temp;
这有点不同。 TMemo
的 Lines
属性 有一个 属性 setter 复制 右侧,而不是采用一个参考。因此,您执行分配给 Lines
的代码是正确的。
你必须明白对象是Delphi中的引用类型,并且这些引用是按值传递的。所以你的程序
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;
永远不会改变调用者的outputList
。事实上,行
outputList:=foundNodesList;
仅设置 getNodeListByClass
过程的 自己的局部变量 outputList
,它只是指向调用者字符串列表的指针的副本。因此,指针的这个副本被更改,但实际对象和调用者指向它的指针保持不变。
此外,即使情况并非如此,您的代码也会有错误,因为
freeandnil(foundNodesList);
销毁字符串列表对象 foundNodesList
,这是 outputList
指向的同一对象。因此,如果调用者能够看到 "new" outputList
(如果它是一个 var
参数),它只会看到一个悬空指针(内存损坏错误)。
你需要的是
procedure TmainForm.getNodeListByClass(const className: string; outputList: TStringList);
var
foundNode: TDomTreeNode;
foundNodesList: TStringlist;
begin
foundNodesList := TStringList.Create;
try
foundNode := nodeFindNodeByClassName(DomTree.RootNode, className);
if Assigned(foundNode) then
getNodeList(foundNode, foundNodesList);
outputList.Assign(foundNodeList);
finally
foundNodeList.Free;
end;
end;
假设您的功能按照我认为的那样进行。但这可以简化为
procedure TmainForm.getNodeListByClass(const className: string; outputList: TStringList);
var
foundNode: TDomTreeNode;
begin
outputList.Clear;
foundNode := nodeFindNodeByClassName(DomTree.RootNode, className);
if Assigned(foundNode) then
getNodeList(foundNode, outputList);
end;
(不知道你是想追加还是替换列表,你得相应调整代码。)
此外,请注意您始终必须保护您的对象,例如使用 try..finally
块。您的代码绝不能泄漏资源(例如内存),即使引发异常也不行!