![]() |
Delphi-Version: 10 Seattle
Freigabe von übergebenen Interface-Instanzen
Habe gerade etwas fest gestellt, von dem ich bisher erwartet hatte, dass es funktioniert. Ich arbeite sehr intensiv mit Interfaces und schaue auch immer, dass ich Objekt- und Interfacereferenzen nicht vermische.
Das heißt, Variable vom Interface-Typ definierten und das Objekt mittels Create der Variable zuweisen. Wenn die Interface-Variable aus dem Scope fällt, wird das Objekt dahinter auch immer schön frei gegeben. So soll das sein! Jetzt hätte ich erwartet, wenn eine Methode eine Interface-Variable übernimmt, und ich beim Aufruf direkt die neu erstelle Objekt-Referenz übergebe, dass der RefCount und die Freigabe korrekt funktionieren. Dem ist anscheinend nicht so. Im Folgenden mal ein Beispiel-Code. Habe an der entsprechenden Stelle einen Kommentar eingefügt...
Delphi-Quellcode:
Ist das logisch? Hätte ich bisher anders erwartet... da mir aber der Speicher voll lief, wurde ich eines besseren belehrt. ;)
type
IMyInterface = interface(IInterface) ['{475ACE39-ECC7-467D-A325-35B2DF22203A}'] procedure DoSomething; end; TMyInterface = class(TInterfacedObject, IMyInterface) private procedure DoSomething; public destructor Destroy; override; end; TForm1 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); private procedure Machwas(const AValue: IMyInterface); public end; var Form1: TForm1; implementation {$R *.dfm} destructor TMyInterface.Destroy; begin ShowMessage('Free!'); end; procedure TMyInterface.DoSomething; begin //... end; procedure TForm1.Button1Click(Sender: TObject); var Value: IMyInterface; begin //Wenn der Aufruf auf diese Weise erfolgt, wird das Objekt NICHT frei gegeben. Machwas(TMyInterface.Create); //So wird das Objekt korrekt frei gegeben Machwas(TMyInterface.Create as IMyInterface); //so wird das Objekt auch korrekt frei geben Value := TMyInterface.Create; Machwas(Value); end; procedure TForm1.Machwas(const AValue: IMyInterface); begin AValue.DoSomething; end; |
AW: Freigabe von übergebenen Interface-Instanzen
Das ist ein abartiger Fallstrick. Das
Delphi-Quellcode:
in deiner Methode bedeutet für den Compiler "Die Referenz wird nicht verändert. Ach komm, sparen wir uns gleich die Referenzzählung". Tödlich, wie du siehst.
const
Ich finde es auch schrecklich, die einzige Hilfe ist sich das eigentlich sinnvolle
Delphi-Quellcode:
bei Interface-Argumenten abzugewöhnen.
const
|
AW: Freigabe von übergebenen Interface-Instanzen
Zitat:
Danke für die Info. |
AW: Freigabe von übergebenen Interface-Instanzen
Ich habe mir das Machwas(TMyInterface.Create); abgewöhnt.
Seitdem funktioniert's :) Das const lasse ich daher. Es soll m.W. ein paar CPU Anweisungen einsparen. |
AW: Freigabe von übergebenen Interface-Instanzen
Das const ist bei häufigen Aufrufen spürbar schneller, ja.
Das direkte Übergeben macht man eben nicht. Wenn man es so schreibt, geht es ja. Das hast du ja jetzt vermutlich auch so:
Delphi-Quellcode:
var
Value: IMyInterface; begin Value := TMyInterface.Create; Machwas(Value); |
AW: Freigabe von übergebenen Interface-Instanzen
Ja das ist eine "unschönheit" im Delphi Compiler. Ist nicht konsistent in der Hinsicht. Wurde bei stackoverflow auch schon
hoch und runter diskutiert. Zumindest ein Hint sollte da auftauchen. ![]() Gruss Fritz PS: Hallo Andreas :-) |
AW: Freigabe von übergebenen Interface-Instanzen
Immerhin geht ja folgendes:
Delphi-Quellcode:
Machwas(TMyInterface.Create as IMyInterface);
Dann muss man nicht unbedingt eine Variable anlegen. Allerdings muss man dran denken.... :? Gruß Andreas PS: Hallo Fritz. :-D |
AW: Freigabe von übergebenen Interface-Instanzen
In diese Falle sind schon Generationen von Delphi Entwicklern getappt:
![]() ![]() ![]() Aber trotzdem wird es von den Verantwortlichen leider immernoch wegdiskutiert: ![]() |
AW: Freigabe von übergebenen Interface-Instanzen
Wenn ich keine Factory für die Klasse habe, mache ich es einfach so...
Delphi-Quellcode:
Und läuft...
type
TMyInterface = class(TInterfacedObject, IMyInterface) private procedure DoSomething; public destructor Destroy; override; Class Function Construct : IMyInterface; end; implementation procedure TForm1.Button1Click(Sender: TObject); begin Machwas(TMyInterface.Construct); end; |
AW: Freigabe von übergebenen Interface-Instanzen
Was machst Du dann bei Parametern im Constructor? Alles doppelt pflegen?
Und wie gewährleistest Du das die Benutzer Deiner Klasse das auch so anwenden? |
Alle Zeitangaben in WEZ +1. Es ist jetzt 03:23 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz