![]() |
Delphi-Version: XE
Generisches ToString für Enumerations
Hallo zusammen,
habe gerade mal wieder ein Problem bzgl. meiner Log-Klasse. Ich hätte gerne folgendes:
Delphi-Quellcode:
Das Problem hierbei ist ja, dass die Add-Methode keine Ahnung von TTestEnum hat, d.h. ich sollte diese generisch gestalten, was an sich ja kein Problem wäre. Jetzt kommt allerdings das ABER: bei Generics gibts ja keine Einschränkung, dass ich eben nur Enumeration-Typen übergeben kann und somit funktioniert folgendes ja nicht:
type
TTestEnum = (teOne, teTwo, teThree {...}); TTestEnumSet = set of TTestEnum; var a : TTestEnum; b : TTestEnumSet; begin a := teOne; TLog.Add(a); // -> liefert dann den String "teOne" // DAS HIER MAL NICHT BEACHTEN!!! //b := [teTwo, teThree]; //TLog.Add(b); // -> Liefert den String "[teTwo, teThree]" end;
Delphi-Quellcode:
Habt ihr eine Idee, wie man das Dilemma umgehen kann?
uses
TypInfo; procedure TLog.Add<T>(Value: T); var s : string; begin s := GetEnumName(TypeInfo(T), Integer(Value)); // <- [DCC Fehler] Project1.dpr(27): E2089 Ungültige Typumwandlung { ... } end; |
AW: Generisches ToString für Enumerations
|
AW: Generisches ToString für Enumerations
Jupp, entweder
![]() SizeOf(Integer) <> SizeOf(TTestEnumSet) Versuch mal Byte, Word, LongWord/LongInt oder UInt64/Int64. |
AW: Generisches ToString für Enumerations
Selbst mit Ord() scheitert das ganze:
Delphi-Quellcode:
PS: Beachtet das mit dem set mal noch nicht.
[DCC Fehler] Project1.dpr(30): E2008 Inkompatible Typen
|
AW: Generisches ToString für Enumerations
Jetzt bleibt noch die Frage, wo Delphi gerade den Fehler meldet (beim 1. oder 2. Parameter)?
Bernhard |
AW: Generisches ToString für Enumerations
Ich habs so gelöst:
Delphi-Quellcode:
class function TEnumGen<T>.GetName(AVal: T): string;
var bVal : Byte; begin move(AVal,bVal,SizeOf(T)); Result:=GetEnumName(TypeInfo(T),bVal); end; |
AW: Generisches ToString für Enumerations
Ha, ich habs :stupid:
Delphi-Quellcode:
Der Tipp von himitsu war gut. Jetzt muss ich nur noch testen, ob das auch immer passen sollte. In meinen Fall passts jedenfalls. Aber man kann ja auch gewisse Werte für die Enum-Elemente definieren. Melde mich gleich wieder.
TLog = record
class procedure AddEnum<T>(V: T); static; end; class procedure TLog.AddEnum<T>(V: T); begin Writeln(GetEnumName(TypeInfo(T), PByte(@V)^)); end; @daywalker: klar, so gehts auch :) -- EDIT: So, habe mich jetzt nochmals ein wenig mit diesen Enumerations befasst und bin auf ein weiteres Problem gestoßen, welches dieses Zitat auf den Punkt bringt: Zitat:
|
AW: Generisches ToString für Enumerations
In der Logging Bibliothek, die wir in der Firma nutzen (recht bekanntes kommerzielles Produkt) ist das so gelöst, dass man bei LogEnum den Ordinalwert und den TypInfo übergibt. Da ist allerdings auch nix mit Generics.
|
AW: Generisches ToString für Enumerations
Ich unterstütze alles ab Delphi 2010, da ich teilweise rege Verwendung der neuen RTTI mache. Nachdem es auch die netten Generics gibt, will ich dem Nutzer der Log-Komponente (Hauptnutzer bin wohl ich :mrgreen:) so viel wie möglich abnehmen. Daher mein Ansatz, aber danke für den Hinweis.
-- Edit: Hier noch schnell der Record mit den entsprechenden Methoden. Die Methode StrToEnum() gibt es in der TypInfo-Unit auch und heißt dort GetEnumValue(). Allerdings liefert GetEnumValue() einen Integer und müsste somit nochmals zusätzlich gecastet werden, was hier nicht der Fall ist -> Typsicherheit!
Delphi-Quellcode:
Wenn noch wer was dran auszusetzen hat, dann nur her damit ;)
TEnumHelper = record
class function EnumToStr<T>(Value: T): String; static; class function StrToEnum<T>(Value: String): T; static; end; class function TEnumHelper.EnumToStr<T>(Value: T): String; var ti : PTypeInfo; begin ti := TypeInfo(T); if (ti = nil) then raise Exception.Create('Type has not type information.'); if (ti.Kind <> tkEnumeration) then raise Exception.Create('Type is not an enumeration.'); Result := GetEnumName(ti, PByte(@Value)^); end; class function TEnumHelper.StrToEnum<T>(Value: String): T; var ti : PTypeInfo; i : Byte; pt : ^T; begin ti := TypeInfo(T); if (ti = nil) then raise Exception.Create('Type has not type information.'); if (ti.Kind <> tkEnumeration) then raise Exception.Create('Type is not an enumeration.'); i := GetEnumValue(ti, Value); pt := @i; Result := pt^; end; |
AW: Generisches ToString für Enumerations
Du solltest die Größe deines Enum Typens überprüfen, der muss nämlich nicht immer 1 Byte sein.
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:58 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