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
Seite 2 von 2     12   
Elvis

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

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.008 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#12

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
Elvis

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

AW: Generisches ToString für Enumerations

  Alt 30. Apr 2011, 22:33
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.
Records sind eigentlich dafür da sich eigene Value Typres zu basteln, die auch ohne Garbage Collector wie normale Werte zu benutzen sind.
Klassen sind dafür da um zum Beispiel diese Art von Code zu enthalten. (Vor allem, da es auch noch komplett statisch ist... o_O )
Es gibt natürlich immer sinnvolle Ausnahmen, aber genau das ist hier überhaupt nicht der Fall gewesen.
Ich verbrachte nämlich beim lesen seines Beitrags etwas Zeit um rauszufinden, warum er es als Record deklarieren musste. Bis ich feststellte, dass es gar keinen Grund dafür gibt. Er hatte es einfach so gemacht, sozusagen eine Münze geworfen oder eine erhoffte Optimierung nach Cargo-Cult Style.
Du gibst ja auch keiner Klasse einen I-Präfix, außer wenn es unbedingt, aus irgendeinem drastischen Grund, sein muss.
Wenn du also eine Klasse mit einem I-Präfix siehst, wirst du wohl auch Zeit verbringen herauszufinden, warum der Autor das tun musste. Das gleiche gilt auch hier, nur 2 Nummern weniger dramatisch.
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.008 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#14

AW: Generisches ToString für Enumerations

  Alt 30. Apr 2011, 23:14
Er hatte es einfach so gemacht, sozusagen eine Münze geworfen oder eine erhoffte Optimierung nach Cargo-Cult Style.
Du gibst ja auch keiner Klasse einen I-Präfix, außer wenn es unbedingt, aus irgendeinem drastischen Grund, sein muss.
Wenn du also eine Klasse mit einem I-Präfix siehst, wirst du wohl auch Zeit verbringen herauszufinden, warum der Autor das tun musste. Das gleiche gilt auch hier, nur 2 Nummern weniger dramatisch.
Ich kann nicht hellsehen, aber da ich einige der jüngsten Neuentwicklungen seit Delphi 2009 kenne, würde ich vermuten, dass er sich das von den Jungs bei Embarcadero abgeschaut hat. Die pflegen das nämlich auch (z.B. IOUtils.pas). Soll nicht heißen, dass ich das sonderlich gut finde. Ich finde es im Hinblick auf Testbarkeit (Stichwort: Mocks) eher ziemlich schäbig. Leider tun dem class methods aber auch keinen Abbruch, weil du immer noch ne statische Abhängigkeit hast.
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
 
#15

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

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.008 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#17

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

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.008 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#19

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

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, 38x 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
Seite 2 von 2     12   


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 12:33 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