Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Generics: Ungültige Typumwandlung (https://www.delphipraxis.net/171549-generics-ungueltige-typumwandlung.html)

Codewalker 12. Nov 2012 12:15

Delphi-Version: XE2

Generics: Ungültige Typumwandlung
 
Hallo zusammen.

Mir machen mal wieder die Generics Kopfschmerzen. Ich möchte in einer Settings-Klasse eine generische get-Funktion haben, die mir den gewünschten Typ direkt castet. Das ganze sollte meiner Meinung nach so aussehen:

Delphi-Quellcode:

// Nur als Hinweis:
FValues = TDictionary<string, Variant>;

{ ...}

function TSettings.GetItem<T>(Key: String): T;
begin
  Result := T(FValues[Key]);
end;
Das ganze wollte ich dann z.B. so aufrufen:

Delphi-Quellcode:
var
 a: TMeineKlasse;
 i: Integer;
begin
 a := Settings.GetItem<TMeineKlase>('blabla');
 i := Settings.GetItem<Integer>('neZahl');
 // usw.
Leider bekomme ich als Fehler:
Code:
Ungültige Typumwandlung
bei meinem cast. Warum geht das nicht und was müsste ich denn ändern?

SirThornberry 12. Nov 2012 13:18

AW: Generics: Ungültige Typumwandlung
 
Das hat nichts mit den Genercis zu tun sondern damit das du einen Variant versuchst auf eine Objektinstanz zu casten.

Stevie 12. Nov 2012 13:41

AW: Generics: Ungültige Typumwandlung
 
Zitat:

Zitat von SirThornberry (Beitrag 1190828)
Das hat nichts mit den Genercis zu tun sondern damit das du einen Variant versuchst auf eine Objektinstanz zu casten.

Hat sehr wohl mit Generics zu tun, dass er einen Variant auf T zu hardcasten versucht.

In deinem Fall solltest du zu Rtti.TValue greifen. Das ist der Container, der alles aufnehmen kann, was es so gibt (und nein, Variant kann das nicht).

Delphi-Quellcode:
FValues = TDictionary<string, TValue>;

function TSettings.GetItem<T>(Key: string): T;
begin
  Result := FValues[Key].AsType<T>;
end;
Ein Wort der Warnung an dieser Stelle: Im Gegensatz zu Variant, bei welchem einige implizite Typenkonvertierungen durchgeführt werden, wirft TValue.AsType<T> eine EInvalidCast Exception, wenn das was drin steht, nicht direkt zuweisungskompatibel zu T ist.

Codewalker 12. Nov 2012 15:44

AW: Generics: Ungültige Typumwandlung
 
Das mit
Delphi-Quellcode:
TValue
kannte ich noch nicht. Das klingt deutlich sinniger als Variant. Ich werde das versuchen, danke

Codewalker 12. Nov 2012 16:15

AW: Generics: Ungültige Typumwandlung
 
Okay, sieht für die Abfrage ganz gut aus. Aber ich darf jetzt keine Werte mehr in das Dictionary einfüllen

Delphi-Quellcode:
Data.Add('key', IrgendeinVariant);
Code:
[DCC Fehler] DataQueries.pas(56): E2010 Inkompatible Typen: 'TValue' und 'Variant'
Edit: Habs gefunden.

Delphi-Quellcode:
Data.Add('key', TValue.From<Variant>(Inhalt));
Quelle: http://stackoverflow.com/questions/2...-to-store-data

Stevie 12. Nov 2012 17:22

AW: Generics: Ungültige Typumwandlung
 
Andere Möglichkeit wäre,
Delphi-Quellcode:
TValue.FromVariant
zu benutzen, dann wird nämlich der Datentyp benutzt, der intern im Variant steckt.

Vorteil: Wenn du im Variant nen string stehen hast, wird nicht der Variant, in dem der string steht im TValue gespeichert, sondern der string.
Nachteil: Wie im vorherigen Post erwähnt, geht dir eventuell notwendige implizite Typenkonvertierung verloren

Generell kann ich empfehlen, auf Variants zu verzichten, sofern du einen generischen Ansatz verfolgst. Benutze an Stellen, wo du zur Compiletime den Type nicht kennst, lieber TValue, um Werte auszutauschen. An allen anderen Stellen, benutze den konkreten Datentyp. TValue verfügt für die meisten Standardtypen über überladene Implicit Operatoren, die dir den Aufruf von z.B.
Delphi-Quellcode:
TValue.From<Integer>(i)
ersparen.


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