AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language Warnung vor massivem Einsatz von Generics in Delphi
Thema durchsuchen
Ansicht
Themen-Optionen

Warnung vor massivem Einsatz von Generics in Delphi

Ein Thema von WladiD · begonnen am 16. Dez 2024 · letzter Beitrag vom 25. Sep 2025
 
Redeemer

Registriert seit: 19. Jan 2009
Ort: Kirchlinteln (LK Verden)
1.158 Beiträge
 
Delphi 2009 Professional
 
#24

AW: Warnung vor massivem Einsatz von Generics in Delphi

  Alt 25. Sep 2025, 11:26
Ich möchte das hier nochmal ausgraben.

Ich habe folgende Units:
  • Dictionaries.pas: definiert ein TWuppdiCtionaryInteger<T> = class(TDictionary<Integer, T>) ... end; mit einigen Zusatzfunktionen (z.B. eine ENotFoundException mit dem Namen des fehlenden Keys sowie eine sortierte Liste der Keys). Es gibt sie analog noch mit einigen weiteren Datentypen neben Integer als Key (string, TPoint, usw.).
  • Etwa 10 verschiedene *.Stammdaten.pas: Definieren jeweils 10 bis 20 Records und deklarieren globale Variablen für Dictionaries davon. Zum Beispiel type TWuppdi = record ... end; und var Wuppdis: TWuppdiCtionaryInteger<TWuppdi>; .
  • Cache.pas: Erstellt und füllt beim Start des Programms die Dictionary-Variablen, im genannten Beispiel also Wuppdis . Das ganze läuft in einem Thread.
Alle DCUs, die *.Stammdaten.pas verwenden, blähen sich auf. Insbesondere natürlich Cache.dcu, die bei mir jetzt so um die 8 MiB groß ist.

Was ich probiert habe:
  1. Ich habe eine *.Dictionarytypen.pas hinzugefügt, die den verwendeten TWuppdiCtionaryInteger<T> einen Namen gibt: type TDictWuppdis = TWuppdiCtionaryInteger<TWuppdi>; . Danach habe ich eine *.Cache.pas hinzugefügt, mit den var Wuppdis: TDictWuppdis; , und die uses der anderen Units entsprechend angepasst. Das hat die EXE aber nur weiter aufgebläht. Die allgemeine Cache.dcu ist gleich groß geblieben.
  2. Ich habe dann von *.Dictionarytypen.pas die Typdefinition in eine Vererbung geändert: type TDictWuppdis = class(TWuppdiCtionaryInteger<TWuppdi>); Dementsprechend musste ich in der allgemeinen Cache.pas den verwendeten Konstruktor auf den des neuen Typs ändern. Das hat funktioniert.
  3. Also habe ich anschließend nochmal die Typdefinition in einen Alias zurückgeändert, alles andere aber so gelassen (also z.B. weiter den Konstruktor der neuen Namen verwendet). Dann war es wieder so groß wie nach Versuch 1. Cache.dcu hingegen wurde sogar noch marginal größer als in Versuch 1.
  4. Anschließend habe ich ausgehend von Versuch 2 den Inhalt beider neuen Units zurück in *.Stammdaten.pas kopiert und die beiden neuen Dateien gelöscht. Gleiches Ergebnis wie Versuch 2. Reicht also auch.

tl;dr: Ich möchte Devids Post somit zwei Dinge hinzufügen:
  • Es reicht nicht aus, seinen Generics-verwendenden Typen einfach nur einen Namen zu geben (type IntDict = TDictionary<Integer>; ), selbst wenn man nur noch diesen neuen Namen verwendet. Man muss sie zwingend ableiten (type IntDict = class(TDictionary<Integer>); ), was dann bekanntlich die Verwendung des neuen Namens im Regenfall erzwingt.
  • Edge Case: Das Problem tritt auch auf, wenn – um bei Devids Beispiel zu bleiben – eine globale Variable des Typs TList<Integer> in Unit A deklariert und in Unit B erstellt wird. Schon der Aufruf des Konstruktors legt offenbar die komplette Klasse in der DCU ein weiteres Mal an. Sind Variablen des Typs TList<Integer> allerdings nur in Unit A deklariert, kann auch die neue Klasse dort abgeleitet werden und es muss keine Unit C geben.

Mich verwundert aber: In beiden erfolgreichen Versuchen (2 und 4) ist neben der EXE nur die allgemeine Cache.dcu kleiner geworden. Andere DCUs sind nicht kleiner geworden. Ich habe das darauf geschoben, dass der Konstruktur ursprünglich die Klassendeklaration (Wuppdis := TWuppdiCtionaryInteger<TWuppdi>.Create(); ) enthielt, kann mir dann aber nicht erklären, warum ein Alias ohne Ableitung (type IntDict = TDictionary<Integer>; ) und dessen ausschließliche Verwendung keinerlei Verbesserung bringen.

inb4: Ja, ich weiß, globale Variablen sind Böse und so.
Delphi 2010.
Janni
2005 PE, 2009 PA, XE2 PA

Geändert von Redeemer (25. Sep 2025 um 11:28 Uhr)
  Mit Zitat antworten Zitat
 


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:19 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