Ist das bei einer Prozedur innerhalb einer Methode anders?
Ja! Nicht, was die Variablen betrifft, aber bei dem Zeitpunkt der Ausführung. Eine lokale Prozedur L innerhalb einer Methode M kann nur innerhalb dieser Methode M aufgerufen werden. Für alles außerhalb von M ist sie schlichtweg nicht sichtbar. Die lokalen Variablen von M sind dann, bei entsprechender Anordnung des Quelltexts, innerhalb von L verfügbar. Eine Anonyme Methode A kann aber auch außerhalb des Kontexts von M aufgerufen werden, in dem sie deklariert wurde. Trotzdem kann sie auf die lokalen Variablen von M zugreifen, obwohl M zu diesem Zeitpunkt schon längst beendet wurde.
Gerne verwendete Beispiele sind sicher die Methoden Synchronize und Queue aus TThread. Diesen kann man entweder parameterlose Methoden (procedure of object) oder eben auch parameterlose Anonyme Methoden mitgeben. Bei den simplen Methoden muss man die eigentlich benötigten Parameter in Felder der abgeleiteten Thread-Klasse stecken (Nein, globale Variablen sind da bei Todesstrafe verboten!). Das mag bei Synchronize noch gehen, da dort der Aufruf, wie der Name vermuten lässt, synchron geschieht. Bei Queue ist das aber nicht so. Da bietet sich eine Anonyme Methode an, die auf eine lokale Variable zugreift.
Hier mal ein typischerweise absolut sinnfreies Beispiel:
Delphi-Quellcode:
program Project36;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
System.Generics.Collections,
System.Classes;
type
TMyThread = class(TThread)
public
class procedure ExecuteThread;
end;
TMyThread1 = class(TMyThread)
protected
procedure Execute; override;
end;
TMyThread2 = class(TMyThread)
protected
procedure Execute; override;
function MakeAnonMeth(Value: Integer): TThreadProcedure;
end;
class procedure TMyThread.ExecuteThread;
var
instance: TMyThread;
begin
instance := Self.Create;
try
instance.WaitFor;
finally
instance.Free;
end;
end;
procedure TMyThread1.Execute;
var
I: Integer;
aProc: TThreadProcedure;
begin
aProc := Procedure
begin
Writeln(Format('%d Prozent', [I]));
end;
for I := 0 to 100 do begin
Synchronize(aProc);
end;
end;
procedure TMyThread2.Execute;
var
I: Integer;
begin
for I := 0 to 99 do begin
Queue(MakeAnonMeth(I));
end;
Synchronize(MakeAnonMeth(100));
end;
function TMyThread2.MakeAnonMeth(Value: Integer): TThreadProcedure;
begin
result := Procedure
begin
Writeln(Format('%d Prozent', [Value]));
end;
end;
begin
TMyThread1.ExecuteThread;
TMyThread2.ExecuteThread;
Readln;
end.