Delphi Programming

and software in general.

Thursday, July 31, 2008

Anonymous methods - Variable Scope?

I am reading about all the Tiburón goodies with great pleasure, but I find myself uncertain of how some aspects of anonymous methods actually will work.

What variables that are in scope at the point of definition will be allowed used within the anonymous method, and which references should be avoided?

Can the method be defined without being assigned to a local variable, ie directly as a parameter to a call?

With reference to the articles on the TGridViewController, would it be possible to convert this (class method pointer)...

procedure TViewDirectory.DefineAttributes;
begin
CreateTextColumn('Name', GetFileName, 300);
CreateTimeColumn('Date', GetFileDate, 100, taCenter);
CreateIntegerColumn('Size', GetFileSize, 100, taRightJustify);
end;

// Note that Dir is a protected class property of TViewDirectory

function TViewDirectory.GetFileDate(const Row:Integer):TDateTime;
begin
Result := FileDateToDateTime(Dir.Entry[Row].Time);
end;

function TViewDirectory.GetFileName(const Row:Integer):String;
begin
Result := Dir.Entry[Row].Name;
end;

function TViewDirectory.GetFileSize(const Row:Integer):Integer;
begin
Result := Dir.Entry[Row].Size;
end;
to this? I.e. in-line declared anonymous methods

procedure TViewDirectory.DefineAttributes;
begin
CreateTextColumn(function (const row:integer):String;
begin
Result := Dir.Entry[row].Name;
end, 'Name', 300);

CreateTimeColumn(function (const row:integer):TDateTime;
begin
Result := FileDateToDateTime(Dir.Entry[row].Time);
end, 'Time', 100, taCenter);

CreateIntegerColumn(function (const row:integer):Integer
begin
Result := Dir.Entry[row].Size;
end, 'Size', 100, taRightJustify);
end;
Apart from in-parameter definition (and any related syntactical mistakes I might have made), the problem here would be the reference to Dir. Since Dir is a class property (or private variable), it seems possible that this would be quite safe.

What about local variables?
Is this legal?
procedure DefineAttributes;
var
Reg : TRegistry;
Key, Value : TStringList;
begin
Reg := TRegistry.Create;
key := TStringList.Create;
Value := TStringList.Create;
try
Reg.OpenKeyReadOnly('\Software\Somewhere');
Reg.GetKeyNames(Key);
Reg.GetValueNames(Value);

// we have ensured that GetRowCount returns the correct count

CreateTextColumn( function (const row:integer):string;
begin
Result := Key[row];
end, 'Key');

CreateTextColumn( function (const row:integer):string;
begin
Result := Value[Row];
end, 'Value');

finally
FreeAndNil(Value);
FreeAndNil(Key);
FreeAndNil(Reg);
end;
end;
I am really looking forward to learn more on this!