Bejárók Delphi - érvénytelen

Iterátor Delphi

A dokumentáció szerint. által támogatott iterációs a tömb elemeinek, karakter soronként, a beállított értékek (készlet), és, a legtöbb Érdekes, hogy egy speciálisan elkészített osztályok és feljegyzések. A tömbök és szimbólumok minden nyilvánvaló róla készletek tudja magyarázni egy kicsit részletesebben:

Ez egy példa egy tipikus felhasználása iterációk alatt készletek. Iteráció nélkül kellene megtenni:

Nem csak ez kényelmetlen, köteles lenne egy új sort az eljárás, amikor egy új zászlót adunk a készlet.

Most az érdekes jellemzője iterátorokat. Megengedett, hogy egy osztály a saját iterátorokat. Például a saját listáját, vagy TStringList tarthatja végigmegy a listán. A legtöbb szabvány az ő osztályok és támogatás:

Support iteráció és felveheti a saját kategóriájában. Ehhez szükségünk van egy segítő osztály a bejáró (vagy a számlálóra, ahogy szeretné). A fő osztályba kell egy függvény GetEnumerator. amely létrehozza és visszaadja egy példány a helper osztály:

Iterátor magát tartalmaznia kell a MoveNext függvény visszatérési hamis A, ha több elem Nincs ingatlan jelenlegi, amely visszaadja az aktuális elem:

Itt kész megbocsátani a bejáró. Nem lehet, hogy valamit javítani? Például a tapasztalt delfist azonnal észre, hogy minden egyes használata iterátor létrehozását igényli egy tárgy, és az objektumok létrehozását, emlékszünk elég lassú művelet. Hála Istennek, tudjuk, hogy egy bejáró rekordot. Minden, ami kell változtatni a kódot -, hogy távolítsa el a hívást, hogy az örökölt létrehozása:

Így kapunk egy meglehetősen gyors iteráció önkényes tartályba. Tudod, hogy magát TMyCollection rekordot. A különleges ellátás teljesítménye nem fog, hiszen csak akkor jön létre egyszerre, de ha szükség van rá más célokra - mindig szívesen látjuk. Mindenesetre, ha jól emlékszem, hogyan Delphi megvalósított kapcsolatok keresztben. Osztályok:

A nyilvánvaló kérdés: lehet, hogy nem hoznak létre semmilyen tárgyat az iterációban vagy rekord? Nem csak vissza a GetEnumerator utalást is, ha úgy véljük, hogy az iteráció kizárólag egy időben?

A helyes válasz: nem, akkor nem. Delphi automatikusan megsemmisíti a bejáró használat után. GetEnumerator Ha visszatér a fő célja, hogy meg kell semmisíteni. Semmit lehet, akkor nem írhatja felül a Destroy.

Valaki meg fogja kérdezni, lehetséges, hogy kapcsolja be a fókusz el ezt a rekordot. Nyilvántartások nem megsemmisült? Igen, nyilvántartások nem semmisülnek meg, de ezek szivárog, és nincs értelme. Ne feledje, hogy a bejegyzések érték szerint adódnak át; Ez azt jelenti, hogy a GetEnumerator függvény nem ad vissza egy hivatkozás a rekord, és egy adatblokk, annak teljes tartalmát. Akkor, persze, hogy visszatérjen maga is lehívható:

Ez csak azt jelenti, hogy Ön alkotók TMyRecord új rekord, és másolja a régi tartalmat. Ez a megközelítés egyébként hasznos lehet egyszerre, például, ha a belsejében TMyRecord kevés a kritikus információkat. Amikor belépünk a több szál esetben előnyös, nem blokkolja az objektum időtartama alatt a bejárást, és másolja azt a későbbi válogatás, és azonnal engedje őt.

blokkoló
Ők egyszerű használata iterátorokat, és most lépni a bonyolultabb. A legkényelmesebb iterátorokat, hogy lehetővé teszi tetszőleges kód futtatására idején felsorolás. Ez az, amit használni. Például, hogy túl sok szálbiztosak. Amikor dolgozik több patakok minden programozónak megismétli, mint ez:

Leegyszerűsítjük a design!

Néha ez a megközelítés, mint már mondtam, nagyon könnyű használni - de nem mindig. Gyakran előfordul, hogy mentse az állam szeretné másolni az egész tömböt, annak ellenére, pointerek, és ez nagyon hosszú. Milyen kár, hogy nem tudjuk, akkor, amikor tönkreteszi a szerkezet a Delphi ... vagy lehet?

Mit teszünk most - ez egy kis varázslat. Delphi nem okoz destruktorai a rekord, de véglegesíti annak tartalmát, beleértve az okokat _Release interfészeket. Ezért létrehoz egy felület, amely felszabadítja a zárat _Release.
Először is, szükségünk túlhatározott végrehajtás IInterface:

RefCnt elindultunk csak véletlenül sem megtörni néhány belső optimalizálása Delphi, aki használja ezt az értéket. Általánosságban elmondható, hogy egy bármikor visszatérhet egységet. Célunk nem pusztította el RefCnt nullára csökken; élettartama van beállítva, mint a normál Delphi tárgy, kézi pusztulástól. Amikor elfog egy magára mutató blokkolja fogás objektumot, amikor megjelent - kinyitja.

Most a gyűjtemény maga:

Felhívjuk figyelmét, hogy megtartjuk Gatekeeper, mint egy tárgy. Ha tartotta, mint a felület, akkor állandóan maradt a csapdába esett. „Smart” mutatókat interfészek Delphi úgy vannak elrendezve, hogy automatikusan okozó _AddRef ha egy értéket rendelünk az egy interfész típusú, és automatikusan okozhat _Release klíringbank ezt az értéket.

Mikor megkérdeztük TMyCollectionEnumerator, használjuk az ingatlan, hogy visszatérjen egy bejáró amibe helyezzük egy változó típusú IInterface. Amikor betette a Gatekeeper, Delphi automatikusan _AddRef, blokkoló gyűjtemény. Ha egy rekord elpusztul, Delphi automatikusan befejezi a bejegyzés Gatekeeper törli a területen, és mivel ez egy interfész típus, ami őt _Release - és a gyűjtemény a zárolt.

Ez kétségtelenül egy nagyon kényelmes és gyors módja. Gatekeeper csak egyféle tárgyat olyan gyűjtemény; akkor tudja használni a különböző iterátorokat közvetlenül. Egyszer létre, amikor létrehoz TMyCollection, és szinte nem növeli a feje fölött. Azonban van néhány buktatókat. Bár Delphi biztosítja a pusztítás rekord-bejáró, és tönkretegye azt, hogy a felület tiszta, nem lehet tudni, mikor fog csinálni. A mellékelt kódot végeztem néhány kísérletet, és megállapította, például, hogy bár a hétköznapi bejáró funkció haladéktalanul meg kell semmisíteni, amikor kilép az „a ...”, ezért a fő szerve a konzol alkalmazás iterátorokat-bejegyzések nem pusztulnak egyáltalán. Tehát ezt a technikát kell alkalmazni óvatosan.

szűrők
Egy másik érdekes alkalmazása iterátorokat - szűrőket. Ahelyett, hogy az írás:

Szeretném valahogy így:

A bejárók könnyű csinálni, de felár ellenében - ha használja a rekordokat. Ez többletköltséget - létrehozása egy másik rekord idő alatt. Azt bizonyítják:

Itt az a probléma, hogy a szintaxis Delphi kemény követelményeket támaszt a tárgyat a jobb oldalon a „for ... in” végrehajtása GetEnumerator. Filter funkció, amit írok, meg kell önmagában létrehozni, és visszatér egy tárgyat, és azt a tárgyat kell majd hozzon létre egy másik - a számlálóra. Szeretném tudni, hogy használja ezt a számlálóra legtöbb létrehozott FilterKeepalive tárgy (elvégre ez több nizachem nem szükséges!). Ugyanakkor a magas pontszámokat nem fog működni a már említett okokból: ha csak visszatéríti GetEnumerator „Eredmény: = Self”, valójában másolni a rekord, és nem javítja a helyzetet.

A másik dolog - az osztályokat. Nincs többletköltség ki:

Class egyszerűen visszaadja utalás is. Ha emlékszel, hogy ezt gyűjtemény tilos volt, mert tönkreteszi a Delphi bejáró használat után. Azonban itt is nem csak a kezét, és létfontosságú: ki fogja elpusztítani létre FilterKeepalive osztály idő?

generátorok
Egy másik érdekes alkalmazása iterátorokat annak a ténynek köszönhető, hogy nem kell rendezni a meglévő létesítményeket. A bejáró képes végighaladni az elemek számítva menet közben is. A link a példákban a generációs Fibonacci-számok, és mi fogja megoldani a gyakorlati probléma - és gyorsabban (így természetesen anélkül, osztályok, gyárak és interfészek, Isten ments én).

Hozzunk létre egy bejáró hogy vissza fog térni hozzánk az összes ablakot magas szinten a rendszerben:

Nem probléma vele, de még mindig megadja a kódot. Először hozzon létre egy bejáró magát. Ez nagyon egyszerű, tartalmazza a teljes tömb ablakok talált, és tele létrehozásakor a mester:

Nyilvánvaló, hogy szükségünk van egy gyár, amely létrehoz:

Ez minden. TopLevelWindows függvény a gyár, nincs szükség arra, hogy nem minden fajta műveletek (visszaadott rekord automatikusan kiválasztva). A mellékelt program megy keresztül az összes ablakot, és kinyomtatja azokat a képernyőn (nem elrejteni, ne félj, nem vagyok olyan őrült).

Ui Általánosságban elmondható, hogy az ablakok nem torzulhat. Hagyományos tömbök munka nem rosszabb:

Nos, nos, mint a - fájlokat?

Itt is nyugodtan kezelhetjük egy tömb, de takarékoskodni az a tény, hogy ha a középső enumeratsii azt szeretnénk, hogy egy kis szünetet - mi nem követett el felesleges kéréseket a fájlrendszer. Nos, általában, tömbök, ismét nem kiosztani. Vedd iterációs-osztják a verem, ha jól értem.