Reputation: 2023
the following line of code fails :
...
ProcessStringLIst(ChecklistBox_CheckedStrings(MyCheckListBox));
....
// support functions
function ProcessStringLIst (alst : TStringlist);
begin
/// .... process the stringlist
end;
function ChecklistBox_CheckedStrings(aCheckListBox: TCheckListBox): TStringList;
var
i: Integer;
begin
result.Clear;
for i := 0 to aCheckListBox.Items.Count - 1 do
if aCheckListBox.Checked[i] then
result.Add(aCheckListBox.Items[i])
end;
because inside ChecklistBox_CheckedStrings the result is not yet assignd with data . Can I avoid the 4 line version as below :
templist := TStringlist.Create;
temList := ChecklistBox_CheckedStrings(MyCheckListBox);
ProcessStringLIst(templist);
templist.free;
Upvotes: 2
Views: 2026
Reputation: 612794
In your code the function return value is not initialized, and then your first line of code does:
result.Clear;
Because you have not initialized result
, anything can happen. If you enable compiler warnings then the compiler will tell you this.
You need to make up your mind whether or not you want the function to return a newly created string list object, or to work with one created by the caller. Let's assume you opt for the latter. Then your function becomes a procedure like this:
procedure GetChecklistBox_CheckedStrings(aCheckListBox: TCheckListBox;
aStringList: TStringList);
var
i: Integer;
begin
aStringList.Clear;
for i := 0 to aCheckListBox.Items.Count - 1 do
if aCheckListBox.Checked[i] then
aStringList.Add(aCheckListBox.Items[i])
end;
The calling code then becomes:
templist := TStringlist.Create;
try
GetChecklistBox_CheckedStrings(MyCheckListBox, templist);
ProcessStringList(templist);
finally
templist.free;
end;
You must use try/finally
if you want to protect your program against memory leaks.
And the other way looks like this:
function CreateCheckListBox_CheckedStrings(aCheckListBox: TCheckListBox): TStringList;
var
i: Integer;
begin
Result := TStringList.Create;
try
for i := 0 to aCheckListBox.Items.Count - 1 do
if aCheckListBox.Checked[i] then
Result.Add(aCheckListBox.Items[i])
except
Result.Free;
raise;
end;
end;
.....
templist := CreateCheckListBox_CheckedStrings(MyCheckListBox);
try
ProcessStringList(templist);
finally
templist.free;
end;
Again, it's easy to put either of these methods into a class helper to make the calling syntax look more clear.
My most important pieces of advice:
try/finally
correctly.Upvotes: 4