![]() |
Delphi-Version: 5
Enum in String mehrere Overloaded Funktionen zu einer einzigen zusammenfassen?
Folgende Funktion befindet sich in meinem Code und davon eine für jedes meiner Enums
Delphi-Quellcode:
Ist es möglich diese Funktion so abzuändern, dass ich alle meine Enums an eine einzige Funktion schicken kann, welche mir dann den String zurückgibt wie oben zu sehen auch?
// EnumGetString(TWProcesses.wpIdle) würde string 'wpIdle' zurückgeben
function EnumGetString(aEnumValue: TWProcesses): string; var bVal: Byte; begin Move(aEnumValue, bVal, SizeOf(TWProcesses)); Result := GetEnumName(TypeInfo(TWProcesses), bVal); end; |
AW: Enum in String mehrere Overloaded Funktionen zu einer einzigen zusammenfassen?
|
AW: Enum in String mehrere Overloaded Funktionen zu einer einzigen zusammenfassen?
Zitat:
|
AW: Enum in String mehrere Overloaded Funktionen zu einer einzigen zusammenfassen?
Man kann den Compiler nicht zufällig anweisen keine Schlussfolgerungen über den generischen Typ anzustellen sodass der Benutzer den generischen Typ angeben muss?
Alternativ kann man, wenn einen das stört, ja einen Integer übergeben und steckt in seine "EnumZuString"-Methode dann nicht mehr "myEnum" sondern "Ord(myEnum)" rein. |
AW: Enum in String mehrere Overloaded Funktionen zu einer einzigen zusammenfassen?
Zitat:
Zitat:
|
AW: Enum in String mehrere Overloaded Funktionen zu einer einzigen zusammenfassen?
Zitat:
Für den Fall dass ein Enum nicht mehr als 128 (oder 256?) Einträge enthält ginge ja so etwas hier, aber perfekt ist das auch nicht :|. Mein Favorit ist der zweite der drei Aufrufe.
Delphi-Quellcode:
program Project16;
{$APPTYPE CONSOLE} {$R *.res} uses System.TypInfo; type TEnum = record public class function GetName<T>(const enum: T): String; overload; static; public class function GetName<T>(const ordinalValue: System.ShortInt): String; overload; static; end; { TEnum } class function TEnum.GetName<T>(const enum: T): String; var ordinalValue: Integer; begin ordinalValue := Default(Integer); Move(enum, ordinalValue, SizeOf(T)); Result := GetEnumName( TypeInfo(T), ordinalValue ); end; class function TEnum.GetName<T>(const ordinalValue: System.ShortInt): String; begin Result := GetEnumName( TypeInfo(T), ordinalValue ); end; type TMyEnum = (uno, dos, tres); var myEnum: TMyEnum; begin myEnum := TMyEnum.dos; // Nicht typsicher, myEnum könnte genauso gut ein Float sein WriteLn( TEnum.GetName<TMyEnum>(myEnum) ); // Typsicher, WENN man sich zwingt EXPLIZIT "TMyEnum" anzugeben WriteLn( TEnum.GetName<TMyEnum>(myEnum) ); // Sieht typischer aus, aber statt myEnum könnte man ebenso gut "42" reinstecken WriteLn( TEnum.GetName<TMyEnum>( Ord(myEnum) ) ); ReadLn; end. |
AW: Enum in String mehrere Overloaded Funktionen zu einer einzigen zusammenfassen?
Zitat:
Delphi-Quellcode:
und
class
Delphi-Quellcode:
keine Constraints zulassen. Wobei Constraints eh nur ein Versuch sind ein viel prägnanteres Design-Flow abzuschwächen:
interface
Delphi-Quellcode:
An dieser Stelle meldet sich der Delphi-Compiler obwohl ich die Klasse nirgends verwende mit einem Fehler, weil er einfach so davon ausgeht, dass
class procedure TGenericClass<TEnum>.Print(Enum: TEnum);
var E: TEnum; begin for E := Low(Enum) to High(Enum) do begin WriteLn(Ord(Enum)); end; end;
Delphi-Quellcode:
kein Enum-Typ ist, sondern eine Klasse (bzw. untypisiert ist, oder was der Compiler auch immer an dieser Stelle als Standardtyp annimt). Dies ist mir relativ unverständlich, wenn ich mal mit den Templates in C++ vergleiche (diese sind auf der trivialsten Ebene praktisch Generics):
TEnum
Der Code in Template-Funktionen wird erst dann verifiziert, sobald er auch generiert wird. Und generiert wird er einmalig für jeden distinkten Datentyp den ich tatsächlich irgendwo im Code an die Template-Klasse übergebe.
Delphi-Quellcode:
würde also ohne Probleme funktionieren, während
TGenericClass<TIrgendeinExistierendesEnum>.Print(MyEnum)
Delphi-Quellcode:
korrekterweise den Fehler erzeugt, dass man
TGenericClass<TIrgendeineKlasse>.Print(MyClassInstance)
Delphi-Quellcode:
natürlich nicht auf einen Klassentyp anwenden darf.
Low
Die C++ Templates sind im Gegensatz zu den Delphi Generics sozusagen Context-aware. Am Ende kommt jedenfalls bei raus, dass man unter Delphi gezwungen wird ziemlich viele nicht typsichere Operationen durchzuführen, bei denen man höchstens mit viel Mühe und unter Verwendung der RTTI eine teilweise Typsicherheit wiederherstellen kann: ![]() Edit: @Günther: Und wer hindert dich bei deiner Klasse daran einfach
Delphi-Quellcode:
aufzurufen?
TEnum.GetName<TForm1>(Form1)
|
AW: Enum in String mehrere Overloaded Funktionen zu einer einzigen zusammenfassen?
Die Antworten sind ja schon erstaunlich.
Wäre es bei so vielen Komplikationen einen schönen Code zu bekommen nicht die einfachste Möglichkeit mehrere overloaded Funktionen zu fahren? |
AW: Enum in String mehrere Overloaded Funktionen zu einer einzigen zusammenfassen?
Zitat:
Delphi-Quellcode:
Du solltest halt nur aufpassen, dass du dieser Klasse als Typ tatsächlich nur Enums übergibst und nichts anderes. Im Debug-Mode würdest du zwar im Zweifelsfalle eine Runtime-Exception bekommen, aber bei Code-Pfaden, die nicht oft ausgeführt werden, entdeckt man so einen Laufzeitfehler teilweise erst recht spät.
type
TEnumHelper<TEnum> = record public class function GetName(Value: TEnum): String; overload; static; end; { TEnumHelper<TEnum> } class function TEnumHelper<TEnum>.GetName(Value: TEnum): String; var TypInfo: PTypeInfo; TypData: PTypeData; V: Integer; begin TypInfo := TypeInfo(TEnum); {$IFDEF DEBUG} if (TypInfo^.Kind <> tkEnumeration) then begin raise Exception.Create('Invalid generic type.'); end; {$ENDIF} TypData := GetTypeData(TypInfo); case TypData^.OrdType of otSByte, otUByte: V := PByte(@Value)^; otSWord, otUWord: V := PWord(@Value)^; otSLong, otULong: V := PInteger(@Value)^; end; Result := GetEnumName(TypeInfo(TEnum), V); end; Alternativ müsste auch das hier gehen:
Delphi-Quellcode:
class function TEnumHelper<TEnum>.GetName(Value: TEnum): String;
var TypInfo: PTypeInfo; V: Integer; begin TypInfo := TypeInfo(TEnum); {$IFDEF DEBUG} if (TypInfo^.Kind <> tkEnumeration) then begin raise Exception.Create('Invalid generic type.'); end; {$ENDIF} case SizeOf(TEnum) of 1: V := PByte(@Value)^; 2: V := PWord(@Value)^; 4: V := PInteger(@Value)^; end; Result := GetEnumName(TypeInfo(TEnum), V); end; |
AW: Enum in String mehrere Overloaded Funktionen zu einer einzigen zusammenfassen?
Dumme Frage: Warum nimmst du statt dem:
Zitat:
Delphi-Quellcode:
Assert(TypInfo^.Kind = tkEnumeration, 'Invalid generic type.');
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 05:19 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