AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

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
Benutzerbild von Stevie
Stevie

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

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
 
#2

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
 
#3

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
Benutzerbild von Stevie
Stevie

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

AW: Generisches ToString für Enumerations

  Alt 1. Mai 2011, 10:52
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...
Wie ich bereits sagte. In die eine Richtung geht es nur wegen dem ToString. Das wandelt alles in seine String Repräsentation um (genau wie das ToString in TObject). Es findet hier keine Typenkonvertierung statt. Bei deinem Versuch einen String in den Typen umzuwandeln bemüht die RTTI intern die Typenkonvertierung, sofern es sich um sehr ähnliche Typen handelt (Float typ, ordinal typ, etc). Und TValue ist nicht für eine Typenkonvertierung darüber hinaus gedacht und funktioniert auch nicht, wie du gesehen hast. Du kannst damit nichtmal nen string in nen integer umwandeln, obwohl das eigentlich technisch kein Probelm wäre.
Stefan
“Simplicity, carried to the extreme, becomes elegance.” Jon Franklin

Delphi Sorcery - DSharp - Spring4D - TestInsight

Geändert von Stevie ( 1. Mai 2011 um 10:54 Uhr)
  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 1. Mai 2011, 13:33
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...
Allein aufgrund der automatischen Garbage Collection bei Records kann ich verstehen, warum es so gemacht ist, wie es gemacht ist. Sonst müsstest du ja jedes mal ein TValue-Objekt erzeugen und freigeben, wenn du damit arbeiten willst. Records machen das halt sehr viel bequemer. Klar, in meinem Fall ändert sich nicht wirklich viel, aber ich hab mir mal den TValue-Record näher angeschaut und allein schon diese Zeile spricht für sich, wie ich finde:
Delphi-Quellcode:
TValue = record
public
  { ... }
  class function From<T>(const Value: T): TValue; static;
  { ... }
end;
Wäre TValue eine Klasse, dann müsste man die Speicherverwaltung teilweise intern, ebenso aber auch extern durch den Programmierer vornehmen, dass immer alles passt und keine Speicherleaks entstehen. Klar, man könnte den Record (bzw. dann evtl. die Klasse) anders gestalten, aber was genau spricht gegen eine solche Verwendung?

Ich bin echt gerne bereit, meine Ansichten zu ändern, wie schon gesagt, aber ich verstehe den Grund, warum ich das tun sollte, nicht wirklich?! Ich habe extra nochmals auf Wikipedia nachgelesen, wofür Records (bzw. Structs) eigentlich da sind, aber nachdem deren Funktionalität erweitert wurde, sehe ich weniger Probleme darin auch deren Vorteile zu verwenden.
»Remember, the future maintainer is the person you should be writing code for, not the compiler.« (Nick Hodges)
  Mit Zitat antworten Zitat
Benutzerbild von Stevie
Stevie

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

AW: Generisches ToString für Enumerations

  Alt 1. Mai 2011, 14:10
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...
Allein aufgrund der automatischen Garbage Collection bei Records kann ich verstehen, warum es so gemacht ist, wie es gemacht ist. Sonst müsstest du ja jedes mal ein TValue-Objekt erzeugen und freigeben, wenn du damit arbeiten willst. Records machen das halt sehr viel bequemer. Klar, in meinem Fall ändert sich nicht wirklich viel, aber ich hab mir mal den TValue-Record näher angeschaut und allein schon diese Zeile spricht für sich, wie ich finde:
Delphi-Quellcode:
TValue = record
public
  { ... }
  class function From<T>(const Value: T): TValue; static;
  { ... }
end;
Wäre TValue eine Klasse, dann müsste man die Speicherverwaltung teilweise intern, ebenso aber auch extern durch den Programmierer vornehmen, dass immer alles passt und keine Speicherleaks entstehen. Klar, man könnte den Record (bzw. dann evtl. die Klasse) anders gestalten, aber was genau spricht gegen eine solche Verwendung?

Ich bin echt gerne bereit, meine Ansichten zu ändern, wie schon gesagt, aber ich verstehe den Grund, warum ich das tun sollte, nicht wirklich?! Ich habe extra nochmals auf Wikipedia nachgelesen, wofür Records (bzw. Structs) eigentlich da sind, aber nachdem deren Funktionalität erweitert wurde, sehe ich weniger Probleme darin auch deren Vorteile zu verwenden.
Ihr redet aneinander vorbei. Bei TValue handelt es sich um einen Wertetypen. Bei deinem record nicht, denn er hat keinen State sondern nur 2 Methoden. Und dafür kann man auch ohne Probleme eine Klasse benutzen, weil man für die Benutzung von class methods nix instanzieren muss. Aber wie ich bereits sagte, spielt es für diesen konkreten Fall (Containertyp für parametriesierte Methoden) keine Rolle, ob du eine Klasse mit class methods nutzt oder einen record mit static methods.

Übrigens:
Du könntest auch einen record helper für TValue schreiben
Und schau dir mal die Implementierung von TRttiEnumerationType.GetValue in der Rtti.pas an.
Stefan
“Simplicity, carried to the extreme, becomes elegance.” Jon Franklin

Delphi Sorcery - DSharp - Spring4D - TestInsight

Geändert von Stevie ( 1. Mai 2011 um 14:27 Uhr)
  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 3. Mai 2011, 19:40
Delphi-Quellcode:
TApEnumerations = class
public
  class function EnumToStr<T>(const Value: T): String; static;
  class function StrToEnum<T>(const Value: String): T; static;

  class function SetToStr<T>(const Value: T): String; static;
  class function StrToSet<T>(const Value: String): T; static;
end;
So, habe das ganze nun überarbeitet und um die Methoden SetToStr<T>() und StrToSet<T>() erweitert. Zudem habe ich hier nicht mehr den Anspruch die neue RTTI zu nutzen, da diese ja nur die alte RTTI-Methoden kapselt und so etwas langsamer ist -- klar, man kann hier drüber streiten, aber es soll hier um die Funktionalität gehen

Weiterhin habe ich den record durch class ersetzt, da ich wohl das Argument verstanden habe, warum ich hier eigentlich class verwenden sollte.

In diesem Sinne, wettert drauf los

PS: Ich sollte noch sagen, dass StrToSet<T>() als Typen den set-Typen erwartet (z.B. TTestEnumSet) und als Parameter eine komma-separierte Aufzählung, die in eckigen Klammer platziert ist -- Beispiel: '[taOne, taTwo, taThree]' . (ist quasi die Umkehrfunktion von SetToStr<T> -- wer hätte es gedacht )

-- Edit: Habe das ganze nun mal in eine Unit gepackt und in den Anhang gesteckt. Dadurch wird der Beitrag dezent übersichtlicher.
Angehängte Dateien
Dateityp: pas ApEnumerations.pas (3,7 KB, 39x aufgerufen)
»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 ( 4. Mai 2011 um 16:06 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort


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 19:22 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