AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren

Generisches ToString für Enumerations

Ein Thema von s.h.a.r.k · begonnen am 30. Apr 2011 · letzter Beitrag vom 3. Mai 2011
Antwort Antwort
Seite 1 von 2  1 2   
Benutzerbild von rollstuhlfahrer
rollstuhlfahrer

Registriert seit: 1. Aug 2007
Ort: Ludwigshafen am Rhein
1.529 Beiträge
 
Delphi 7 Professional
 
#1

AW: Generisches ToString für Enumerations

  Alt 30. Apr 2011, 15:05
Jetzt bleibt noch die Frage, wo Delphi gerade den Fehler meldet (beim 1. oder 2. Parameter)?

Bernhard
Bernhard
Iliacos intra muros peccatur et extra!
  Mit Zitat antworten Zitat
daywalker9

Registriert seit: 1. Jan 2010
Ort: Leer
594 Beiträge
 
Delphi XE3 Professional
 
#2

AW: Generisches ToString für Enumerations

  Alt 30. Apr 2011, 15:32
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;
Lars
  Mit Zitat antworten Zitat
Benutzerbild von s.h.a.r.k
s.h.a.r.k

Registriert seit: 26. Mai 2004
3.159 Beiträge
 
#3

AW: Generisches ToString für Enumerations

  Alt 30. Apr 2011, 15:34
Ha, ich habs

Delphi-Quellcode:
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;
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.

@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 von http://delphi.wikia.com/wiki/GetEnumValue_Routine:
Be aware that Typeinfo will be lost when the enumeration is given different ordinal values. With the next enumeration example it's not possible to use GetEnumValue and will result in 'E2134 Type 'TTestType' has no type info'
Schade, aber man kann daran wohl nix ändern.
»Remember, the future maintainer is the person you should be writing code for, not the compiler.« (Nick Hodges)

Geändert von s.h.a.r.k (30. Apr 2011 um 16:07 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Stevie
Stevie

Registriert seit: 12. Aug 2003
Ort: Soest
4.058 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#4

AW: Generisches ToString für Enumerations

  Alt 30. Apr 2011, 16:14
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.
Stefan
“Simplicity, carried to the extreme, becomes elegance.” Jon Franklin

Delphi Sorcery - DSharp - Spring4D - TestInsight
  Mit Zitat antworten Zitat
Benutzerbild von s.h.a.r.k
s.h.a.r.k

Registriert seit: 26. Mai 2004
3.159 Beiträge
 
#5

AW: Generisches ToString für Enumerations

  Alt 30. Apr 2011, 16:17
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 ) 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:
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;
Wenn noch wer was dran auszusetzen hat, dann nur her damit
»Remember, the future maintainer is the person you should be writing code for, not the compiler.« (Nick Hodges)

Geändert von s.h.a.r.k (30. Apr 2011 um 16:33 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Stevie
Stevie

Registriert seit: 12. Aug 2003
Ort: Soest
4.058 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#6

AW: Generisches ToString für Enumerations

  Alt 30. Apr 2011, 16:50
Du solltest die Größe deines Enum Typens überprüfen, der muss nämlich nicht immer 1 Byte sein.
Stefan
“Simplicity, carried to the extreme, becomes elegance.” Jon Franklin

Delphi Sorcery - DSharp - Spring4D - TestInsight
  Mit Zitat antworten Zitat
Benutzerbild von s.h.a.r.k
s.h.a.r.k

Registriert seit: 26. Mai 2004
3.159 Beiträge
 
#7

AW: Generisches ToString für Enumerations

  Alt 1. Mai 2011, 02:49
Du solltest die Größe deines Enum Typens überprüfen, der muss nämlich nicht immer 1 Byte sein.
Da hat der Herr wohl vollkommen recht, baue ich morgen ein Aber im großen und ganzen müsste das der Compiler sogar abfangen, da man ja einen Enum angeben muss, der im Moment ja immer 1 Byte groß ist. Bei den Enums, bei denen man Ordinalwerte angeben kann, wird ja eine Exception geworfen, da gar keine Typeinformationen vorhanden sind.

  1. Warum ein Record? Ernsthaft, wenn jmd irgendwo etwas sieht, was keine Klasse ist, wird er sich denken, dass es einen sehr guten Grund gab. Aber den gibt es hier überhaupt gar nicht.
    Solche ÖHM.... Momente haben in APIs nix zu suchen.
Ich habe es mir wahrlich im Source der VCL abgeschaut und versteh auch nicht den Sinn, warum ich das nicht machen sollte. Selbst TValue ist ein solcher Record, ebenso viele Dinge aus der neuen RTTI. Mir ist schon klar, wofür Records eigentlich gedacht sind, aber wo genau ist das Problem, dass ich Records verwende? Das kann dem Nutzer des Codes doch gänzlich egal sein, oder? Er ruft die Methode exakt gleich auf, bis auf dass anstatt record einfach class steht, was er eigentlich nicht sieht. Ich habe jetzt nicht das schlagende Argument gesehen, warum das denn unbedingt eine Klasse sein muss. Klar, man kann jetzt darüber streiten, was man mit Records alles machen können sollte und was nicht, aber ich sehe hier weniger ein Problem. Aber wie so oft, ich lasse mich gerne belehren
  1. Wenn du schon D2010 nutzt, dann nutze es auch.
    Ich habe es nicht ausprobiert und spreche den neuen Krams von Delphi nicht fließend, aber wenn ich eine generische Methode zum Wandeln in einen String ab D2010 schreiben müsste, würde das wohl so aussehen:
    TValue.From<T>(deinWert).AsString();
Okay, überzeugt. Habs gerade geändert. Allerdings geht das hier nicht: Result := TValue.From<String>(Value).AsType<T>; Endet in einer Exception:
Code:
Im Projekt Project1.exe ist eine Exception der Klasse EInvalidCast mit der Meldung 'Ungültige Typumwandlung' aufgetreten.
Hatte jetzt aber keine Lust mehr da lange zu testen
[...] oder eine erhoffte Optimierung nach Cargo-Cult Style. [...]
WTF? Was für ein Style?
»Remember, the future maintainer is the person you should be writing code for, not the compiler.« (Nick Hodges)
  Mit Zitat antworten Zitat
Elvis

Registriert seit: 25. Nov 2005
Ort: München
1.909 Beiträge
 
Delphi 2010 Professional
 
#8

AW: Generisches ToString für Enumerations

  Alt 1. Mai 2011, 09:37
Okay, überzeugt. Habs gerade geändert. Allerdings geht das hier nicht: Result := TValue.From<String>(Value).AsType<T>; Endet in einer Exception:
Code:
Im Projekt Project1.exe ist eine Exception der Klasse EInvalidCast mit der Meldung 'Ungültige Typumwandlung' aufgetreten.
Hatte jetzt aber keine Lust mehr da lange zu testen
Hmm, hatte mir nur TValue in den API Docs auf Embacadings.com angesehen. Hatte einfach erwartet dass es in beide Richtungen geht. Embarcadings scheint wohl auf Öhm-Momente in ihren APIs viel Wert zu legen, oder einfach nur keinen Anspruch zu haben...

Zitat:
[...] oder eine erhoffte Optimierung nach Cargo-Cult Style. [...]
WTF? Was für ein Style?
http://en.wikipedia.org/wiki/Cargo_c...mming#Overview
Robert Giesecke
I’m a great believer in “Occam’s Razor,” the principle which says:
“If you say something complicated, I’ll slit your throat.”
  Mit Zitat antworten Zitat
Elvis

Registriert seit: 25. Nov 2005
Ort: München
1.909 Beiträge
 
Delphi 2010 Professional
 
#9

AW: Generisches ToString für Enumerations

  Alt 30. Apr 2011, 20:02
Wenn noch wer was dran auszusetzen hat, dann nur her damit
Klaro...
Delphi-Quellcode:
TEnumHelper = record
  class function EnumToStr<T>(Value: T): String; static;
  class function StrToEnum<T>(Value: String): T; static;
end;
  1. Warum ein Record? Ernsthaft, wenn jmd irgendwo etwas sieht, was keine Klasse ist, wird er sich denken, dass es einen sehr guten Grund gab. Aber den gibt es hier überhaupt gar nicht.
    Solche ÖHM.... Momente haben in APIs nix zu suchen.
  2. Wenn du schon D2010 nutzt, dann nutze es auch.
    Ich habe es nicht ausprobiert und spreche den neuen Krams von Delphi nicht fließend, aber wenn ich eine generische Methode zum Wandeln in einen String ab D2010 schreiben müsste, würde das wohl so aussehen:
    TValue.From<T>(deinWert).AsString();
Robert Giesecke
I’m a great believer in “Occam’s Razor,” the principle which says:
“If you say something complicated, I’ll slit your throat.”
  Mit Zitat antworten Zitat
Benutzerbild von Stevie
Stevie

Registriert seit: 12. Aug 2003
Ort: Soest
4.058 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#10

AW: Generisches ToString für Enumerations

  Alt 30. Apr 2011, 20:48
Warum ein Record? Ernsthaft, wenn jmd irgendwo etwas sieht, was keine Klasse ist, wird er sich denken, dass es einen sehr guten Grund gab. Aber den gibt es hier überhaupt gar nicht.
Solche ÖHM.... Momente haben in APIs nix zu suchen.
Wo ist der Unterschied einer statischen Klasse oder einem Rekord in diesem Fall?
Delphi unterstützt nämlich keine Typenparameter in einfachen Routinen.

Wenn du schon D2010 nutzt, dann nutze es auch.
Ich habe es nicht ausprobiert und spreche den neuen Krams von Delphi nicht fließend, aber wenn ich eine generische Methode zum Wandeln in einen String ab D2010 schreiben müsste, würde das wohl so aussehen:
Hier stimme ich dir vollstens zu, habe ich auch vorhin nicht mehr dran gedacht, sonst hätt ich es erwähnt
Dennoch kleine Korrektur: TValue.From<T>(Value).ToString denn AsString versucht, den Typen in einen string umzuwandeln, das wird fehlschlagen.
Stefan
“Simplicity, carried to the extreme, becomes elegance.” Jon Franklin

Delphi Sorcery - DSharp - Spring4D - TestInsight

Geändert von Stevie (30. Apr 2011 um 20:55 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2   

Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:05 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