Meistens müssen Sie beim Programmieren in Delphi keine Komponente dynamisch erstellen. Wenn Sie eine Komponente in einem Formular ablegen, übernimmt Delphi die Komponentenerstellung automatisch, wenn das Formular erstellt wird. In diesem Artikel wird die korrekte Methode zum programmgesteuerten Erstellen von Komponenten zur Laufzeit beschrieben.
Dynamische Komponentenerstellung
Es gibt zwei Möglichkeiten, Komponenten dynamisch zu erstellen. Eine Möglichkeit besteht darin, ein Formular (oder eine andere TComponent) zum Eigentümer der neuen Komponente zu machen. Dies ist eine gängige Praxis beim Erstellen von Verbundkomponenten, bei denen ein visueller Container die Unterkomponenten erstellt und besitzt. Auf diese Weise wird sichergestellt, dass die neu erstellte Komponente zerstört wird, wenn die besitzende Komponente zerstört wird.
Um eine Instanz (ein Objekt) einer Klasse zu erstellen, rufen Sie deren Methode "Create" auf. Der Create-Konstruktor ist a Klassenmethodeim Gegensatz zu praktisch allen anderen Methoden, auf die Sie bei der Delphi-Programmierung stoßen, bei denen es sich um Objektmethoden handelt.
Beispielsweise deklariert die TComponent den Create-Konstruktor wie folgt:
Konstruktor Create (AOwner: TComponent); virtuell;
Dynamische Erstellung mit Eigentümern
Hier ist ein Beispiel für die dynamische Erstellung Selbst ist eine TComponent oder ein TComponent-Nachkomme (z. B. eine Instanz einer TForm):
mit TTimer. Erstellen Sie (Selbst) tun
Start
Intervall: = 1000;
Aktiviert: = False;
OnTimer: = MyTimerEventHandler;
Ende;
Dynamische Erstellung mit einem expliziten Aufruf zum Freigeben
Die zweite Möglichkeit, eine Komponente zu erstellen, ist die Verwendung Null als Eigentümer. Beachten Sie, dass Sie in diesem Fall das von Ihnen erstellte Objekt auch explizit freigeben müssen, sobald Sie es nicht mehr benötigen (oder Sie erstellen ein Speicherleck). Hier ist ein Beispiel für die Verwendung von nil als Eigentümer:
mit TTable. Create (nil) do
Versuchen
DataBaseName: = 'MyAlias';
TableName: = 'MyTable';
Öffnen;
Bearbeiten;
FieldByName ('Busy'). AsBoolean: = True;
Post;
schließlich
Kostenlos;
Ende;
Dynamische Erstellung und Objektreferenzen
Es ist möglich, die beiden vorherigen Beispiele zu erweitern, indem das Ergebnis des Aufrufs Create einer Variablen zugewiesen wird, die lokal zur Methode gehört oder zur Klasse gehört. Dies ist häufig wünschenswert, wenn auf die Komponente müssen später verwendet werden oder wann Umfang Probleme, die möglicherweise durch "With" -Blöcke verursacht werden, müssen vermieden werden. Hier ist der TTimer-Erstellungscode von oben, der eine Feldvariable als Referenz auf das instanziierte TTimer-Objekt verwendet:
FTimer: = TTimer. Schaffe (Selbst);
mit FTimer tun
Start
Intervall: = 1000;
Aktiviert: = False;
OnTimer: = MyInternalTimerEventHandler;
Ende;
In diesem Beispiel ist "FTimer" eine private Feldvariable des Formulars oder visuellen Containers (oder was auch immer "Self" ist). Wenn Sie über Methoden dieser Klasse auf die FTimer-Variable zugreifen, sollten Sie vor der Verwendung überprüfen, ob die Referenz gültig ist. Dies geschieht mit der Funktion "Zugewiesen" von Delphi:
wenn zugewiesen (FTimer) dann FTimer. Aktiviert: = True;
Dynamische Erstellung und Objektreferenzen ohne Eigentümer
Eine Variation davon besteht darin, die Komponente ohne Eigentümer zu erstellen, aber die Referenz für eine spätere Zerstörung beizubehalten. Der Konstruktionscode für den TTimer würde folgendermaßen aussehen:
FTimer: = TTimer. Create (nil);
mit FTimer tun
Start
...
Ende;
Und der Zerstörungscode (vermutlich im Destruktor des Formulars) würde ungefähr so aussehen:
FTimer. Kostenlos;
FTimer: = null;
(*
Oder verwenden Sie die Prozedur FreeAndNil (FTimer), mit der eine Objektreferenz freigegeben und die Referenz durch nil ersetzt wird.
*)
Das Festlegen der Objektreferenz auf Null ist beim Freigeben von Objekten von entscheidender Bedeutung. Der Aufruf von Free überprüft zuerst, ob die Objektreferenz Null ist oder nicht, und wenn dies nicht der Fall ist, ruft er den Destruktor Destroy des Objekts auf.
Dynamische Erstellung und lokale Objektreferenzen ohne Eigentümer
Hier ist der TTable-Erstellungscode von oben, der eine lokale Variable als Referenz auf das instanziierte TTable-Objekt verwendet:
localTable: = TTable. Create (nil);
Versuchen
mit localTable tun
Start
DataBaseName: = 'MyAlias';
TableName: = 'MyTable';
Ende;
...
// Später, wenn wir den Bereich explizit angeben möchten:
localTable. Öffnen;
localTable. Bearbeiten;
localTable. FieldByName ('Busy'). AsBoolean: = True;
localTable. Post;
schließlich
localTable. Kostenlos;
localTable: = nil;
Ende;
Im obigen Beispiel ist "localTable" a lokale Variable in derselben Methode deklariert, die diesen Code enthält. Beachten Sie, dass es nach dem Freigeben eines Objekts im Allgemeinen eine sehr gute Idee ist, den Verweis auf Null zu setzen.
Ein Wort der Warnung
WICHTIG: Mischen Sie einen Aufruf von Free nicht mit der Übergabe eines gültigen Besitzers an den Konstruktor. Alle vorherigen Techniken funktionieren und sind gültig, aber die folgenden sollten treten niemals in Ihrem Code auf:
mit TTable. Erstellen Sie (selbst) tun
Versuchen
...
schließlich
Kostenlos;
Ende;
Das obige Codebeispiel führt zu unnötigen Leistungseinbußen, wirkt sich geringfügig auf den Speicher aus und kann zu schwer zu findenden Fehlern führen. Finde heraus warum.
Hinweis: Wenn eine dynamisch erstellte Komponente einen Eigentümer hat (angegeben durch den AOwner-Parameter des Konstruktors "Erstellen"), ist dieser Eigentümer für die Zerstörung der Komponente verantwortlich. Andernfalls müssen Sie Free explizit aufrufen, wenn Sie die Komponente nicht mehr benötigen.
Artikel ursprünglich geschrieben von Mark Miller
In Delphi wurde ein Testprogramm erstellt, um die dynamische Erstellung von 1000 Komponenten mit unterschiedlichen anfänglichen Komponentenzahlen zeitlich zu steuern. Das Testprogramm wird unten auf dieser Seite angezeigt. Das Diagramm zeigt eine Reihe von Ergebnissen aus dem Testprogramm und vergleicht die Zeit, die zum Erstellen von Komponenten sowohl mit als auch ohne Eigentümer benötigt wird. Beachten Sie, dass dies nur ein Teil des Treffers ist. Eine ähnliche Leistungsverzögerung ist zu erwarten, wenn Komponenten zerstört werden. Die Zeit zum dynamischen Erstellen von Komponenten mit Eigentümern ist 1200% bis 107960% langsamer als die zum Erstellen Komponenten ohne Eigentümer, abhängig von der Anzahl der Komponenten auf dem Formular und der Komponente erstellt.
Das Testprogramm
Warnung: Dieses Testprogramm verfolgt und gibt keine Komponenten frei, die ohne Eigentümer erstellt wurden. Wenn diese Komponenten nicht verfolgt und freigegeben werden, spiegeln die für den dynamischen Erstellungscode gemessenen Zeiten die Echtzeit zum dynamischen Erstellen einer Komponente genauer wider.
Quellcode herunterladen
Warnung!
Wenn Sie eine Delphi-Komponente dynamisch instanziieren und später explizit freigeben möchten, übergeben Sie immer nil als Eigentümer. Andernfalls können unnötige Risiken sowie Probleme mit der Leistung und der Codewartung entstehen. Lesen Sie den Artikel "Eine Warnung zum dynamischen Instanziieren von Delphi-Komponenten", um mehr zu erfahren ...