TStringList local variable not initialized to nil - why?
-
21-02-2021 - |
Question
I am using this code to check whether TStringList
is created or not:
procedure TForm1.Button1Click(Sender: TObject);
var
sVariable : TStringList;
begin
if not Assigned(sVariable) then
sVariable:= TStringList.Create;
end;
But the condition is False
always, why does that happen? How do I check if TStringList
object is created or not?
P.s. I am aware of a similar question asked, I tried the solution posted in that one, but it is not working for me.
La solution
You can assume that the object is not created and the variable initialized with garbage (because it's a local variable). Just create your StringList and everything is fine.
Autres conseils
When you allocate an object reference on the stack, it is filled with random values (i.e. the previous values on the stack - which may be nil in some border cases). This is by design.
In order to check if the variable is initialized, you'll have first to set it manually to nil
. This is a very fast assignment.
A typical code pattern may be:
procedure TForm1.Button1Click(Sender: TObject);
var
sVariable : TStringList;
begin
sVariable := nil; // initialize explicitely
try
(...) // in this hidden part sVariable may be instantiated
if not Assigned(sVariable) then // instantiate if not already done
sVariable:= TStringList.Create;
(...)
finally
sVariable.Free; // will do nothing if sVariable=nil
end;
end;
Note that in the above code, I've included a (mandatory IMHO) try...finally
block to release the memory. If sVariable
was not allocated, it is still nil
, and in this case sVariable.Free
will do nothing. It is an usual best practice pattern in Delphi.
First of all: the code you published makes no sense. Because sVariable is a local variable it is always uninitialized. But unlike to variables in object-scope, uninitialized doesn't implies that it is nil. Delphi won't set local variables to nil. So sVariable contains a completly random value. Assigned() only checks if the value is nil - not if it points to a valid instance of an object.
After your update of the question, what I see, seems to be quite normal.
When you define an object variable (sVariable) it doesn't get initialized, that you have to do with the Create constructor. In this case you don't even have to check for whether it exists or not.
procedure TForm1.Button1Click(Sender: TObject);
var
sVariable : TStringList;
begin
sVariable:= TStringList.Create;
//Work with the stringlist e.g add items:
sVariable.Add('Blah');
//Make sure it finally gets freed
sVariable.Free;
end;
You can do this directly because it's a local variable
procedure TForm1.Button1Click(Sender: TObject);
var
sVariable : TStringList;
begin
sVariable:= TStringList.Create;
end;