Einzelnen Beitrag anzeigen

Der schöne Günther

Registriert seit: 6. Mär 2013
6.159 Beiträge
 
Delphi 10 Seattle Enterprise
 
#10

AW: Automatische Referenzzählug bei Interfaces

  Alt 21. Sep 2021, 16:48
Ich bin davon ausgegangen das Delphi dann den Speicher beim Verlassen des Blocks oder der Schleife automatisch freigibt. Das würde ja die "try finally free" Konstrukte sparen.
Die Erklärung ist man dir etwas schuldig geblieben:

Du hast völlig Recht wenn du meinst dass eine Variable vom Typ "Interface" automatisch freigegeben wird wenn ihr Referenzzähler auf Null geht. Bei einer lokalen Variable ist das üblicherweise der Fall wenn der Gültigkeitsbereich (for-Schleife, begin/end-Block, ...) zu Ende ist.

Nicht der Fall ist das natürlich wenn die Referenz noch irgendwo anders hin weitergegeben und dort gespeichert wird.


Bei den Inline-Variablen ist hier ein Sonderfall, der eigentlich keiner ist:

Angenommen du hast eine Klasse TTerm = class(TInterfacedObject, ITerm) .
Wenn du eine lokale Variable anlegst dann kann die bspw. vom Typ TTerm oder ITerm sein. Wenn du schon ein Interface hast, dann solltest du das auch benutzen und sparst dir, wenn du eine neue Instanz anlegst, auch gleich das try..finally mit. So wie man es schon immer auch von Strings oder dynamischen Arrays kennt...

Jetzt der Stolperstein:
Wenn du bspw. sagst var meinTerm := TTerm.Create() , dann fahr doch mal später mit der Maus über meinTerm und schau was der Computer meint von welchem Typ das ist. Erstaunt? Woher soll der Computer auch wissen dass für dich ein ITerm besser wäre? Du hast ja ganz explizit TTerm.Create() gesagt.

Und Variablen vom Typ TTerm werden natürlich nicht beim Verlassen des Gültigkeitsbereichs freigegeben, das war ja schon immer so. Wir müssen jetzt also nur einen Weg finden explizit zu sagen dass die Variable bitte vom Typ Interface ist.

Es gibt zwei Möglichkeiten mit denen du den Inline-Variablen nicht abschwören musst, die sind nämlich gar nicht böse.
  1. Du gibst dem Compiler explizit vor, von welchem Typ die Variable sein soll. Das hat man ja früher in den var-Blöcken vor dem begin auch immer getan: var meinTerm: ITerm := TTerm.Create();
  2. Du verwendest einen Getter, Factory-Methode was auch immer, dessen Rückgabetyp direkt vom Typ ITerm ist
  Mit Zitat antworten Zitat