![]() |
for..in Schleifen: Wie in Win32 realisiert?
Wie Danny Thorpe in seinem Blogbeitrag
![]() ![]() ![]()
Delphi-Quellcode:
in Szenarien wie
for <variable> in <container expression> do <statement>;
Delphi-Quellcode:
aber auch
type
TMultiArray = array [0..10, 0..3, 0..9] of Integer; procedure DemoMulti(const table: TMultiArray); var X: Integer; begin for X in table do Writeln(x); end;
Delphi-Quellcode:
unterstützen.
procedure DemoTStrings(const AStrings: TStrings);
var S: string; begin for S in AStrings do Writeln(S); end; Während Danny bei Ordinaltypen und Arrays von speziell vom Compiler verarbeiteten, also CompilerMagic, spricht, schweigt sich John über die Realisierung von Klassen (hier: TStrings), die das neue For-Konstrukt unterstützen sollen, aus. Danny schreibt zwar, dass der Containerausdruck Zitat:
![]() Zitat:
Mir ist unklar, wie eine Delphi-Win32-Klasse unter Verwendung der besherigen Referenzzählung ein bestimmtes Interface implementieren sollte und ein Objekt dieser Klasse in der oben beschriebenen Form aufgerufen werden kann, ohne dass ein Verringern des Referenzzählers nach Gebrauch auf null zu dessen Freigabe führt! Beispiel:
Delphi-Quellcode:
Weiß jemand von Euch hierzu etwas genaueres und ist die Schnittstelle von IEnumerable bekannt?
var
MyStrings: TStrings; S: string; begin MyStrings := TStringList.Create; try //... for s in MyStrings do // use IEnumerable -> _AddRef Writeln(s); finally // leave scope of IEnumerable -> _Release -> .Destroy FreeAndNil(MyStrings); // tries to destroy object again! end; Update: Titel des Themas |
Re: for..in Schleifen: Wie in Win32 realisiert?
Ich glaube, da müssen wir noch etwas länger warten, bis das öffentliches Know-How wird ;-)
...:cat:... |
Re: for..in Schleifen: Wie in Win32 realisiert?
in C# sind die sachen, auf die man in einer foreach-schleife zugreift, readonly, d.h. du kannst sie der schleife nicht unterm hintern wegklauen.
|
Re: for..in Schleifen: Wie in Win32 realisiert?
Zitat:
@Mieze & Chewie Kommt IEnumerable nicht erst mit D9 für Delphi32? Aber zum Problem der etwas hakelig implementierten Pseudo-GC in Delphi32: Ich habe es schon mehrfach erlebt, dass ein Object erst nach beenden der Methode gelöscht wurde. Wenn diese Pseudo-GC dann Free anstatt Destroy aufruft wäre ja alles in Butter. :) (Aus untengenannten Problem habe ich mich mit Interfaces in D32 nicht wirklich ernsthaft befasst. :oops: ) BTW: Eine Überarbeitung der Interfaces in Delphi32 wäre langsam mal angebracht. Ich finde es schon ziemlich nervig wenn ir das Objeckt "unter'm Hinter weggeklaut" wird, nur weil man es als Interface ansprechen will. :roll: |
Re: for..in Schleifen: Wie in Win32 realisiert?
Ich dachte, er wollte (unter anderem) wissen, wie verhindert wird, dass die "Sache", die durchlaufen wird, sich während des Schleifendurchlaufs ändert. Und dann wäre das ne Möglichkeit.
|
Re: for..in Schleifen: Wie in Win32 realisiert?
Zitat:
Zitat:
Zitat:
...:cat:... |
Re: for..in Schleifen: Wie in Win32 realisiert?
Zitat:
|
Re: for..in Schleifen: Wie in Win32 realisiert?
Zitat:
Es könnte jedoch sein, dass sich der Compiler für den Spezialfall der Schleife auf eine Art "GetInterfaceWithoutAffectingRefCount" Nachricht des Objekts beruft, um Methodenzeiger auf die die durch das Interface zu implementierenden Methoden zu bekommen. Technisch möglich wäre dieser Ansatz sogar bei Interfaces, die als Containerausdruck übergeben worden wären. Doch, selbst wenn die For..In-Schleife keine Referenzzählung durchführen würde, könnte Code der Art
Delphi-Quellcode:
Sollte im obigen Beispiel MyObj mehr als ein Element besitzen, könnte die Zeile mit dem For-Ausdruck zu Problemen führen, selbst, wenn hier ohne Referenzzähler gearbeitet wird, spätestens aber der Aufruf von FreeAndNil, denn die Zuweisung von nil auf MyIntf hätte das Objekt bereits zerstört!
var
MyObj: TImplementsIEnumerable; MyIntf: IEnumerable; S: string begin MyObj := TImplementsIEnumerable.Create; try //.. for S in MyObj do // references MyObj -> has to be initiated begin MyIntf := MyObj; // calls _AddRef -> "RefCount" = 1 MyIntf := nil; //calls _Release -> "RefCount" = 0 -> .Destroy end; finally FreeAndNil(MyObj); end; end; Für diesen Spezialfall könnte man dem Compiler vielleicht noch eine besondere Prüfung zumuten, so dass For-Schleifen bei einer internen Verwendung doch mit einer Referenzzählung arbeiten. FreeAndNil wie oben aber auch Aufruf von anderen Methoden, die ihrerseits den Referenzzähler verwenden, sind dann wohl aber nur noch unter größtem Aufwand zur Übersetzungszeit als Fehlerquellen erkennbar... Die angeführten Beispiele zeigen zusammen mit der Idee der Referenz auf Methoden ohne Referenzzählung die von den Delphi-Entwicklern bereits oft als Antwort geltende Idee "Entweder Interfaces oder Objektreferenzen" als denkbare Lösung. :gruebel: |
Re: for..in Schleifen: Wie in Win32 realisiert?
Das hängt in diesem Beispiel von der Implementierung des Enumerators an. Bezieht sich dieser auf das TObject von MyObj, dann kann es zu Problemen kommen. Bezieht er sich jedoch auf IEnumerable, so erhöht auch dieser den Referenzzähler um einen ;-)
...:cat:... |
Re: for..in Schleifen: Wie in Win32 realisiert?
Nach meiner Ansicht gibt es für den Compiler, unter Verwendung der spärlichen Informationen von oben, die Möglichkeit
Lassen wir ersteres außer Acht (siehe vorheriges Posting), hat der Compiler die Möglichkeit, über die Tatsache, dass eine Klasse das Interface implementiert, im Fall von oben auch die Möglichkeit, die Tabelle aller implementierten Interfaces zu erfragen (Achtung, dies schließt dann schon dynamische Proxies aus), um eine Referenz auf die Interfacebeschreibung mitsamt Methodentabelle zu erlangen. Es ist es nicht notwendig, Referenzen zu erhöhen, um die so erlangten Referenzen auf Methoden der Art HasNext und GetNext zu verwenden. Handelt es sich beim Containerausdruck selbst um ein Interface, ist der Aufruf von _AddRef und _Release unproblematisch. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 03:44 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