The first procedure :
procedure TestOne(List : TStringList);
var
TempList : TStringList;
begin
TempList := TStringList.Create;
TempList.Add('Test');
List := TempList;
TempList.Free;
end;
procedure TForm1.Button1Click(Sender : TObject);
var
aList : TStringList;
begin
aList := TStringList.Create;
TestOne(aList);
Memo1.Lines := aList;
end;
When I click button the memo doesn’t show any thing , and the breakpoint show the procedure doesn’t execute this line:
List := TempList;

and I modify the procedure :
procedure TestTwo(List : TStringList);
var
TempList : TStringList;
begin
TempList := TStringList.Create;
TempList.Add('Test');
List.Text := TempList.Text;
//or
List.Assign(TempList);
//List := TempList;
TempList.Free;
end;
this time it works.
so why it can’t use List := TempList; ?
When you pass a variable by value, Delphi makes a copy of the parameter value in the Stack and all the changes made to that parameter inside the method are done over that copy.
That’s the way pascal worked since Turbo Pascal days and maybe since the beginning. Consider this:
Now, when you pass a object as a parameter, you have to remember the object variable is a reference to the object (a pointer to the address where the object is really stored in the heap). But, if you pass the parameter by reference, the above rule still applies: A copy of the reference is made in the stack. Any change you make to that reference inside your method/procedure is done over that copy.
The line
List := TempList;merely changes the reference making it point to a different object in a different memory location. That value is lost when the procedure returns, in the same way the integer value is lost when theTestIntprocedure returns.The fact that the line is never executed is the optimizer in action. Since the new value is never used, the optimizer eliminates the assignment from the final exe and the line is really never executed.
You can change the parameter declaration to pass it by reference (a var parameter), but that’s not a good Idea when working with objects, since you have to take into account who’s responsible to free the object’s memory to avoid memory leaks.
You don’t tell what you’re trying to accomplish, but it looks like Assign is the way to go, since the assignment copies the strings from one list to the other. You have to consider working directly over the List and not use a TempList, like this:
The result, as you can see, is the same.
Edit
Rob pointed something important in the comments, so I will address why the last line of the Button1Click method works:
Memo1.Lines := aList;This looks like a direct assignment, but you must know in that line you’re dealing with a Delphi property.
Looking at how the Lines property of a TCustomMemo is declared:
This means that, when you assign a value to the property, you’re really calling the SetLines method, passing the Value as a parameter, like this:
The SetLines implementation looks like this:
So, you’re finally issuing the same TStrings.Assign call which copies all the strings from the source list to the destination list.
This is the Delphi way to deal with object properties and maintain a clear ownership over the objects. Each component creates and owns it’s own sub-objects, and you create and own your objects.
The assignment operator ( := ) over a property is sintactic sugar to allow the component writer to introduce side effects when reading or writing the values, and to allow you, the programmer to think as if the property was a standard field and enjoy the comfort of that side effects.