Einzelnen Beitrag anzeigen

Thom

Registriert seit: 19. Mai 2006
570 Beiträge
 
Delphi XE3 Professional
 
#19

AW: Speicherleck bei der Verwendung von anonymen Methoden

  Alt 18. Okt 2011, 23:04
Noch eine Merkwürdigkeit im Zusammenhang mit anonymen Methoden:

Eine anonyme Methode ist nach außen hin nur ein einfacher Pointer. Ein SizeOf(TProc) liefert also unter 32 Bit erwartungsgemäß 4 Byte. Im Gegensatz dazu bestehen Objekt-Methoden aus einem Daten- und einem Code-Pointer. Deshalb liefert SizeOf(TMethod)=8 (unter 32 Bit).

Jetzt sollte man natürlich annehmen, daß der doppelt so große Wert von TMethod nicht zuweisungskompatibel zum "kleineren" TProc ist.
Entgegen jeder Logik funktioniert das aber doch: Der Compiler generiert bei einer derartigen Zuweisung einfach eine anonyme Methode und bindet die Variable Self, die zu der Objekt-Methode gehört.
Ich finde dieses Verhalten genial, da damit Ereignishandler wahlweise Objekt- oder anonyme Methoden sein können.

Ein kleines Beispiel:
Delphi-Quellcode:
type
  TNotifyProc = TProc<TObject>; //anstelle von TNotifyEvent

  TMyObject = class
  private
    FValue: Integer;
    FOnChange: TNotifyProc;
    procedure SetValue(Value: Integer);
  public
    property Value: Integer read FValue write SetValue;
    property OnChange: TNotifyProc read FOnChange write FOnChange;
  end;

  TForm1 = class(TForm)
  [...]
  private
    procedure MyObjectChange(Sender: TObject);
  end;

procedure TMyObject.SetValue(Value: Integer);
begin
  if FValue<>Value then
  begin
    FValue:=Value;
    if assigned(FOnChange)
      then FOnChange(Self);
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  MyObject: TMyObject;
begin
  MyObject:=TMyObject.Create;
  try
    MyObject.OnChange:=MyObjectChange;
    MyObject.Value:=1;
    MyObject.OnChange:=procedure(Sender: TObject)
                       begin
                         ShowMessage(IntToStr(TMyObject(Sender).Value));
                       end;
    MyObject.Value:=2;
  finally
    MyObject.Free;
  end;
end;

procedure TForm1.MyObjectChange(Sender: TObject);
begin
  ShowMessage(IntToStr(TMyObject(Sender).Value));
end;
Thomas Nitzschke
Google Maps mit Delphi

Geändert von Thom (18. Okt 2011 um 23:07 Uhr)
  Mit Zitat antworten Zitat