Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   [Fmx] TTimeSpan richtig benutzen ? (https://www.delphipraxis.net/191452-%5Bfmx%5D-ttimespan-richtig-benutzen.html)

Rollo62 18. Jan 2017 07:10

[Fmx] TTimeSpan richtig benutzen ?
 
Hallo zusammen,

in der System.DateUtils unit gibt es ein TTimeSpan.
Das ist eine abstrakte Klasse und enthält abstrakte, virtuelle Funktionen.

Normalerweise würde ich die class variable "TTimeSpan-.Local" benutzen,
aber ich verlasse mich ungerne darauf das das schon jemand für mich initialisiert hat
(Weil es keine initialisation Sektion gibt).

Delphi-Quellcode:
  diTimeZone := (((TTimeZone.Local.UtcOffset.Hours * 60) + TTimeZone.Local.UtcOffset.Minutes) * 60) + TTimeZone.Local.UtcOffset.Seconds;


Dann versuche ich das selbst zu initialisieren:
Delphi-Quellcode:
  with TTimeZone.Create do
  begin
    diTimeZone := (((Local.UtcOffset.Hours * 60) + Local.UtcOffset.Minutes) * 60) + Local.UtcOffset.Seconds;
    Free;
  end;
und bekomme natürlich die Warnings in der Art:
Zitat:

[dccosx Warning] MyDeviceInfo.pas(594): W1020 Constructing instance of 'TTimeZone' containing abstract method 'TTimeZone.DoGetID'
Ich frage mich wie soll diese Klasse benutzt werden (selber ableiten wird es doch wohl nicht sein) ?
Ist TTimeSpan.Local immer und auf Allen Platformen korrent initialisiert ?

Vielleicht ist es ja auch ein Bug, oder ein Feature :stupid:

Rollo

Uwe Raabe 18. Jan 2017 07:22

AW: [Fmx] TTimeSpan richtig benutzen ?
 
Zitat:

Zitat von Rollo62 (Beitrag 1359132)
Ist TTimeSpan.Local immer und auf Allen Platformen korrent initialisiert ?

TTimeSpan zwar nicht (das findet man übrigens in System.TimeSpan), aber TTimeZone.Local ist immer initialisiert, wenn du es benutzt. Dafür sorgt der class constructor:

Delphi-Quellcode:
class constructor TTimeZone.Create;
begin
  { Create the local time-zone too }
  FLocal := TLocalTimeZone.Create;
end;

Rollo62 18. Jan 2017 07:37

AW: [Fmx] TTimeSpan richtig benutzen ?
 
Interessant.

Ich bin davon ausgegangen das man den auch immer explizit aufrufen müsste.

Wann wird der denn aufgerufen, sobald man die Klasse einmal anfasst, egal wo ?

Edit:
Delphi-Quellcode:
    { Specifies the local time zone. Use this property to obtain a TTimeZone instance that identifies
      current user's time zone. }
    class property Local: TTimeZone read FLocal;
Also der ttimeZone.Local hat keinen Getter der die class variable initialisieren könnte ...

Rollo

Fritzew 18. Jan 2017 07:57

AW: [Fmx] TTimeSpan richtig benutzen ?
 
Zitat:

Wann wird der denn aufgerufen, sobald man die Klasse einmal anfasst, egal wo ?
Class constructuren werden während der Initialisierung aufgerufen wenn Die Klasse im Projekt verwendet wird.

also sozusagen in einem versteckten initialize Bereich der Unit.
Quasi: (Pseudocode)

Delphi-Quellcode:
initilalzation
 if isUsed(TmyClass) then // IsUsed wird vom Compiler erzeugt
 TmyClass.create;
end;

Uwe Raabe 18. Jan 2017 08:06

AW: [Fmx] TTimeSpan richtig benutzen ?
 
Zitat:

Zitat von Rollo62 (Beitrag 1359134)
Also der ttimeZone.Local hat keinen Getter der die class variable initialisieren könnte ...

Ist auch nicht nötig. Der class constructor wird zwingend immer vor dem Code ausgeführt, der auf TTimeZone.Local zugreift.

Rollo62 18. Jan 2017 08:28

AW: [Fmx] TTimeSpan richtig benutzen ?
 
Ok, dankesehr.

wieder was dazugelernt :-D

Dann werde ich vielleicht mal einige meiner Klassen überarbeiten wo ich das im Moment in einer globalen Instanz per Getter mache.

Eigentlich bin ich kein Freund von solchen "Compiler" Magics, zumal dadurch womöglich die initialisation Phase immer länger werden könnte, was bei Mobile u.U. sehr schädlich sein kann.
Ich habe mich mit dem Thema aber noch nicht wirklich tiefer auseinandergesetzt.

Hier ist wohl der passende Doku-Abschnitt dazu:
http://docwiki.embarcadero.com/RADSt...le/de/Methoden

Wenn ich die Instanz per Getter-Funktion erzeuge habe ich zumindest die Kontrolle darüber wann das genau passiert (eben dann wenn ich es wirklich brauche, oder eben auch niemals).

Zitat:

In diesem Beispiel überprüft der Compiler, ob TBox tatsächlich in der Anwendung verwendet wird. Falls ja, wird automatisch ein Aufruf des Klassenkonstruktors dem initialization-Abschnitt der Unit hinzugefügt.

Hinweis: In der Regel sorgt der Compiler für die richtige Reihenfolge der Initialisierung von Klassen, in einigen komplexen Szenarien könnte die Reihenfolge aber zufällig werden. Und zwar dann, wenn der Klassenkonstruktor einer Klasse vom Status einer anderen Klasse abhängig ist, der wiederum von der ersten Klasse abhängt.

Hinweis: Der Klassenkonstruktor für eine generische Klasse oder einen Record kann mehrfach ausgeführt werden. Die genaue Anzahl der Ausführungen des Klassenkonstruktors hängt in diesem Fall von der Anzahl der spezialisierten Versionen des generischen Typs ab. Der Klassenkonstruktor für eine spezialisierte TList<String>-Klasse kann beispielsweise mehrfach in derselben Anwendung ausgeführt werden.
Ich vermute mal das diese "versteckte" initialisierung, so wie es im Text oben steht,
IMMER bei Verwendung mit reingelinkt werden, und damit auch IMMER ausgeführt.
Also egal ob die Klasse wirklich in einer Session benutzt wird, oder nicht.
Ausserdem sthat da das die Reihenfolge gehen sollte, aber nicht muss.

Während eine Getter-Funktion erst dann aufgerufen wird wenn der User die Klasse wirklich braucht.

Ich sehe immer noch ein paar Vorteile der Getter-Funktion, oder täusche ich mich da und die class constructoren sind womöglich cleverer als ich dachte ?

Rollo

Fritzew 18. Jan 2017 09:17

AW: [Fmx] TTimeSpan richtig benutzen ?
 
Ich denke das kommt wirklich darauf an was Du benötigst.
Wird die Klasse immer benutzt macht der Class Constructor Sinn, wird die Klasse nur eventuell benutzt und zieht
viele Ressourcen oder benötigt beim Erstellen viel Zeit ist eine Lösung mit getter (lazy ininitialize) eventuell besser. Das zu entscheiden liegt an Dir. Es ist halt eine Möglichkeit.

himitsu 18. Jan 2017 11:56

AW: [Fmx] TTimeSpan richtig benutzen ?
 
Die Class-Constructor aller "verwendeten" Klassen werden vom Delphi immer vor dem Initialization aufgerufen
und die Class-Destructor dementsprechend nach dem Finalization.

Also in Initialization und Finalization sind immer alle Klassen lokalen Klassen initialisiert. (jene, welche auch im Programm einkompiliert gelinkt wurden)

Alle Units in der Interface-Uses-Klausel sind auch immer initialisiert, wenn man sie irgendwo in der eigenen Unit verwendet.
Darum sollte man besser Units immer im Interface einbinden und nur problematische Kreuzverlinkungen in der Implementation.

Die Units in einer Implementation-Uses-Klausel können in Class-Controtor und Initialization uninitialisiert sein, aber im laufenden Programmcode sind die dann auch immer initialisiert.


Vorteil/Nachteil: Initialisierung im Initialisation-Block bindet immer alle da aufgerufenen Klassen ins Programm ein.
Und bei Initialisierung im Class-Constuctor, da kann der Compiler Linker die ganze Klasse weglassen, wenn sie nachher nirgendwo im Programm verwendet wurden.


Pssst, mit FMX/VCL hat das eigentlich nichts zu tun ... gehört eher zur RTL. :zwinker:

Rollo62 18. Jan 2017 14:46

AW: [Fmx] TTimeSpan richtig benutzen ?
 
Hallo Himitzu,

vielen Dank für die weiteren Aufklärungen.

Fmx war in meinem Fall wg. der mobilen Plattformen reingeschrieben,
wo ich speziell "initialisation" Blocks vermeiden möchte, was ich hier aber anscheinend nicht wirklich kann

Damit hat sich das Ganze dann zumindest mit TTimeSpan für mich erledigt.

Nochmal vielen Dank an Alle.

Rollo


Alle Zeitangaben in WEZ +1. Es ist jetzt 20:33 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz