Ist Schlangengift tödlich oder hilfreich ?
Tja, auch bei Interfaces ist der manuelle Aufruf von ._Release() im Normelbetrieb meistens tödlich. Aber es gibt durchaus Anwendungsbereiche in denen die gezielte manuelle Benutzung sehr hilfreich, ja sogar notwenig wird. Zb. bei Listen oder zirkulären Verknüpfungen von Interfaces. Das heist ._Release() ist eine reguläre Methode eines Interfaces und kann manuell aufgerufen werden oder auch nicht. An der Methode selber ist nichts tödlich. Ob die manuelle Benutzung von ._Release() zu unschönen Seiteneffekten führt hängt nur vom Gesamtsystem ab. Delphi ist bemüht möglichst transparent im Hindergrund für dich das Referencecounting der Interfaces durchzuführen. Deine manuellen Aufrufe könnten also mit dem Delphi Mechanismen kollidieren, und das kann tödlich sein. Man kann aber durchaus Interfaces benutzen so das Delphi sich da nicht selber drum kümmert und dann ist ein Aufruf von ._Release; auch nicht mehr so gefährlich, weil wir ja nun sowieso alles manuell machen.
Die Regeln wie und warum du ._Release nicht benutzten solltest werden also durch die Implementierungen im Compiler bestimmt. Benutzt du Interfaces in Delphi so übergibst du die komplette Kontrolle über das Lifetime Management der Interfaces dem Compiler. Der Compiler HAT sicherzustellen das dies sicher (try finally) und immer erfolgt.
Deine Regel lautet: In Delphi werden Interfaces durch den Compiler verwaltet, das ist ein Vorteil für uns und wir mischen uns da nicht weiter ein (._Release), da das meistens nur zu Fehler führen wird.
Wir müssen uns dann vergegenwärtigen was die Methode ._Release() für eine Sourcecode Entsprechnung besitzt. Diese Methode soll die Referenzzählung von Variablen die auf ds gleiche Interface zeigen durchführen. Eine Referenz ist also eine Variable die auf das Interface zeigt. Es können mehrere solche Variablen/Referenzen existieren.
Was sind die Zuweisungs-Operatoren für Referenzen ??
Delphi-Quellcode:
var
A,B: IInterface;
begin
A := CreateInterface;
B := A;
A := nil;
end;
Obige 3 Zeilen SIND die Zuweisungs-Operatoren. Mit ihnen verknüpft der Compiler beo Interfaces die Methoden ._Release() und ._AddRef(). Das erfolgt vollständig transparant, unsichtbar für dich durch den Compiler.
Die Referenzzählung kann nur dann sauber funktionieren wenn der Delphi Compiler die komplette 1 zu 1 Kontrolle beim Mappen der Zuweisungsoperatorten -> := zu den Methoden ._AddRef()/._Release() der betroffenen Interfaces hat.
Ein manueller Aufruf von ._Relase() würde demzufolgen nur eine halb-korrekte Zuweisungoperation von A := nil; darstellen. Dh. mit dem manuellen ._Release() zerstörst du die Logik die sich der Compiler mit seinen Zuweisungen aufgebaut hat.
Klar, wenn man weis was der Compiler wie macht, wird auch ein manuelles ._Release() keinen Schaden anrichten, weil du dann weist das du vorher zu diesem ._Release() ein entsprechendes ._AddRef() aufgerufen hast.
Die Benutzung manueller ._Release() Aufrufe ist also
1.) garnicht nötig in Delphi -> A := nil; macht das Gleiche und das viel sauberer
2.) nicht tödlich wenn vorher ein passendes ._AddRef() aufgerufen wurde, also der Programmierer weis was er tut
3.) unter bestimmmten Umständen, sprich zb. Listen, zirkuläre Referenzen, nicht zu vermeiden und daher wieder sinnvoll
Gruß Hagen