Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi TObject und extended (https://www.delphipraxis.net/151440-tobject-und-extended.html)

friedemann2009 18. Mai 2010 08:46


TObject und extended
 
Liebe Leute,

kurze Frage, da sonst noch nichts dazu gefunden: Wie kann ich einen Extended-Wert als TObject einer TStringlist übergeben?

Delphi-Quellcode:
liste.objects[i]:= TObject(Integer(ExtendedWert));
geht nicht, weil ja wohl Integer und nicht Extended. Mit

Delphi-Quellcode:
liste.objects[i]:= TObject(Extended(ExtendedWert));
gehts aber auch nicht: ungültige Typumwandlung.

Danke und Gruß aus HD,
friedemann

EDIT: Sry, Post im falschen Forum.. Mit Bitte um Verschiebung

mkinzler 18. Mai 2010 08:52

Re: TObject und extended
 
Funktuioniert
Delphi-Quellcode:
liste.objects[i]:= TObject(Integer(Trunc(ExtendedWert)));
?

himitsu 18. Mai 2010 09:02

Re: TObject und extended
 
Granz paßt es da eh nicht rein, da Integer/TObject nur 4 Byte und Extended 10 Byte groß ist.
über Trunc gehen die ganzen Nachkommastellen verloren und zu große Werte passen nicht in den Integer.

Wenn Extended komplett erhalten bleiben soll, wirst du um ein Datenhaltungsobjekt nicht drumrumkommen.

Stevie 18. Mai 2010 09:12

Re: TObject und extended
 
Erst einmal vorweg: Ich persönlich halte es sowieso für schlechten Stil, alles was kein Objekt ist, umzucasten, ums als TObject an eine Stringliste zu hängen.
Zu deinem konkreten Problem:
Ich würde eine simple Hilfsklasse bauen, diese instanzieren, und die Instanz an die Stringliste hängen.
Delphi-Quellcode:
type
  TExtended = class
  private
    FValue: Extended;
  public
    constructor Create(const Value: Extended);
    property Value: Extended read FValue write FValue;
  end;
Delphi-Quellcode:
liste.objects[i]:= TExtended.Create(ExtendedWert);
Denke hierbei daran, dass du die Objekte wieder freigeben musst. Evtl ist ein OwnsObjects = True beim Create deiner Stringliste schon genug, das musst du je nach Verwendung entscheiden.

@mkinzler: Sauber, schön den Nachkommateil wegschneiden :shock:

xZise 18. Mai 2010 09:17

Re: TObject und extended
 
Moin,
willst du denn den Inhalt des Extended Wertes behalten, oder reicht dir ein Integer davon?

Für ersteres müsstest du entweder mit Klassen oder Pointern arbeiten und bei zweiterem nimm mkinzlers Weg. Beziehungsweise er schneidet die Nachkommastellen ab. Alternativ kannst du auch ab-, auf- oder kaufmännisch runden (floor, ceil, round).

Zu den Zeigern (ich hoffe das passt so, habe aber lange nicht mehr damit gearbeitet):
Delphi-Quellcode:
var
  e : Extended;
  p : PExtended;
begin
  e := 3.41;
  New(p); // Einen Zeiger darauf erstellen
  p^ := 3.41; // Ich glaube das ^ ist unnötig
  list.objects[i] := TObject(p); // Ich weiß nicht ob er cast obsolet ist
  ShowMessage(FloatToStr(PExtended(list.objects[i])^));
  Dispose(p); // Den Wert wieder freigeben
end;
MfG
Fabian

friedemann2009 18. Mai 2010 09:31

Re: TObject und extended
 
Vielen Dank für die vielen Antworten.

Nun, ja ich brauche die Nachkommazahlen, sonst wäre ich von vornherein auf Integer gegangen. Das mit den neuen Objekten bzw. Zeigern schaue ich mir mal an, das kenne ich noch nicht. - Die einfachste Lösung wäre wohl, wenn ich den Wert einfach in einen String umwandelte und den dann TObject übergäbe und später im Zweifel via strtofloat wieder zurückholte. Aber ich schau mal.

Danke jedenfalls für die Tipps!

Gruß,
friedemann

xZise 18. Mai 2010 10:10

Re: TObject und extended
 
Naja ich selber würde das nicht in einen String unwandeln, wenn du schon die Quellzahl vorliegen hast.

Wenn du dich nicht an die Pointer traust, nehm die Klasse, aber die erzeugt einiges an Overhead. Ansonsten machst du das mit Pointern, wie ich das Vorgeschlagen habe. Dann nehme dir zwei/drei Methoden:
Delphi-Quellcode:
procedure SetExtended(AList : TStrings; AIndex : Integer; AExtended : Extended);
var
  p : PExtended;
begin
  p := PExtended(AList.Objects[AIndex]);
  if p = nil then
  begin
    New(p);
    AList.Objects[AIndex] := TObject(p);
  end;
  p^ := AExtended;
end;

function GetExtended(AList : TStrings; AIndex : Integer) : Extended;
var
  p : PExtended;
begin
  p := PExtended(AList.Objects[AIndex]);
  if p = nil then
  begin
    raise Exception.CreateFmt('Index ' + IntToStr(AIndex) + ' is not set!');
  end;
  Result := p^;
end;

procedure ClearList(AList : TStrings);
var
  i : Integer;
  p : PExtended;
begin
  for i := 0 to AList.Length - 1 do
  begin
    p := PExtended(AList.Objects[i]);
    if p <> nil then
    begin
      Dispose(p);
      AList.Objects[i] := nil;
    end;
  end;
end;
Wichtig ist nur, dass du beim zerstören der StringList die Methode ClearList aufrufst, damit da keine Speicherlecks entstehen.

MfG
Fabian

himitsu 18. Mai 2010 10:21

Re: TObject und extended
 
Zitat:

Zitat von xZise
nehm die Klasse, aber die erzeugt einiges an Overhead.

einen Hauch an RTTI und pro Wert die 4 Byte mehr ... ich glaub das fällt kaum auf
und die Vorteile eines Objektes(Klasse) in .Objects sollten überwiegen, vorallem da sich neuere StringListen automatisch um die Freigabe kümmern können und man sich so auch noch das Freigeben erspart.

xZise 18. Mai 2010 10:27

Re: TObject und extended
 
Nagut,
ich habe angenommen, dass durch die Prozeduren und so halt mehr Speicher gebraucht wird ;) Aber wenn das nicht der Fall ist, natürlich die Klasse nehmen. Weil wie himitsu das schon gesagt hat, gibt das die StringList selber ja auch netterweise wieder frei :)

MfG
Fabian

himitsu 18. Mai 2010 10:46

Re: TObject und extended
 
Och, der Constructor braucht vielleicht auch nur 10 Byte mehr, aber er vereinfacht wenigstens die Erstellung+Wertzuweisung, als wenn man diese Minimalversion verwenden würde.
Delphi-Quellcode:
type
  TExtended = class
    Value: Extended;
  end;
Delphi-Quellcode:
liste.objects[i] := TExtended.Create(ExtendedWert);
//gegen
liste.objects[i] := TExtended.Create;
TExtended(liste.objects[i]).Value := ExtendedWert;
Und das Property verbraucht beim Aufruf garnichts, da ja direkt an FValue weitergeleitet wird.

Stevie 18. Mai 2010 12:31

Re: TObject und extended
 
Der Constructor verbraucht garnix, einzig Feldvariablen und der Zeiger auf die VMT verbrauchen Speicherplatz in einem Objekt (außerdem noch seit Delphi 2009 ein zusätzlicher Pointer). Somit verbraucht nen TExtended wie oben (egal, ob mit property und/oder constructor) bei 8 Byte Alignment 28 Byte (Delphi 2010) bzw 20 Byte (Delphi 7).

P.S. Es wäre zu überlegen, ob du statt Extended, auch mit Double zurecht kommst, der braucht nur 8 Byte und "passt" (beim standardmäßigen 8 Byte Alignment) besser in den Speicher, so dass nicht immer 6 Byte "verschludert" werden.

mkinzler 18. Mai 2010 12:44

Re: TObject und extended
 
Double hat dafür andere Probleme. Deshalb kann man getrost auf die 6 Bytes pfeifen

shmia 18. Mai 2010 14:11

Re: TObject und extended
 
Zitat:

Zitat von friedemann2009
Die einfachste Lösung wäre wohl, wenn ich den Wert einfach in einen String umwandelte und den dann TObject übergäbe und später im Zweifel via strtofloat wieder zurückholte.

Das geht in die Hose weil Delphi den String inzwischen finalisiert hat.
Die Zeiger in Objects[] zeigen dann auf ungültigen Speicher.

mkinzler 18. Mai 2010 14:23

Re: TObject und extended
 
Zudem man sich durch die Wandlung in einen String weitere Probleme ( Dezimaleinstellungen usw.) einhandelt.


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:53 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