Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Enum-Typ als Parameter übergeben und mit einer Schleife durchgehen (https://www.delphipraxis.net/193636-enum-typ-als-parameter-uebergeben-und-mit-einer-schleife-durchgehen.html)

Glados 23. Aug 2017 22:04


Enum-Typ als Parameter übergeben und mit einer Schleife durchgehen
 
Ich möchte gerne einer Funktion einen Enum-Typen als Parameter übergeben.
Das klappt glaube ich
Delphi-Quellcode:
procedure MyFunc<T>(const Param1: string; Enum: T);
begin
end;
Nun möchte ich gerne in einer Schleife auf die einzelnen Inhalte des Enums zugreifen.
Mit einem festen Enum-Typen in der procedure ist das ja einfach. Aber wie sieht das aus, wenn der Enum-Typ jeder Enum sein kann?

Was ich bisher habe und was nicht funktioniert
Delphi-Quellcode:
var i: Integer;
begin
 for i := Low(Enum) to High(Enum) do
 ...

Zacherl 23. Aug 2017 22:25

AW: Enum-Typ als Parameter übergeben und mit einer Schleife durchgehen
 
Tja, da bist du an eine Grenze der Delphi Generics gestoßen. Da Delphi netterweise keine Constraints auf Enums erlaubt (warum auch immer man das nach Jahren nicht schafft; sollte eigentlich trivial zu implementieren sein), kannst du hier leider höchstens mit Umweg über die RTTI (z.b.
Delphi-Quellcode:
TValue
) oder Hard-Casts tricksen :?

Glados 23. Aug 2017 22:29

AW: Enum-Typ als Parameter übergeben und mit einer Schleife durchgehen
 
Verrätst du mir netterweise wie? :pale:

Zacherl 23. Aug 2017 22:33

AW: Enum-Typ als Parameter übergeben und mit einer Schleife durchgehen
 
Zitat:

Zitat von Glados (Beitrag 1379313)
Verrätst du mir netterweise wie? :pale:

Kommt drauf an, was genau du machen willst, also konkreter gesagt, in welcher Form du die einzelnen Werte weiterverwenden willst.

Glados 23. Aug 2017 22:36

AW: Enum-Typ als Parameter übergeben und mit einer Schleife durchgehen
 
Mit dem genauen Typen vorher bin ich mit Low(DerEnumTyp) und High(DerEnumTyp) durchiteriert.
Und mit der Funktion hier unten habe ich mir den aktuellen Wert als String geholt. Mehr passiert da nicht
Delphi-Quellcode:
function GetName<T>(Value: T): string;
begin
 Result := System.Rtti.TRttiEnumerationType.GetName(Value);
end;

var: i: DerEnumTyp;
begin
for i := Low(DerEnumTyp) to High(DerEnumTyp) do
 s := GetName(DerEnumTyp(i));

Zacherl 23. Aug 2017 22:41

AW: Enum-Typ als Parameter übergeben und mit einer Schleife durchgehen
 
Dann schau dir mal
Delphi-Quellcode:
TRttiEnumerationType
an.
Delphi-Quellcode:
GetMinValue
und
Delphi-Quellcode:
GetMaxValue
sind zwar leider
Delphi-Quellcode:
private
, aber folgende Methoden könnten dir evtl. schon reichen:
Delphi-Quellcode:
function GetNames: TArray<string>;
class function GetName<T{: enum}>(AValue: T): string; reintroduce; static;
class function GetValue<T{: enum}>(const AName: string): T; static;
Ansonsten hätte ich hier noch eine Möglichkeit explizit an Min und Max zu gelangen (Auszug aus einem Code, der den generischen Enum Typ in einen Ordinalwert konvertiert und dabei zur Sicherheit einige Assertions aufgrund der RTTI Infos ausführt):
Delphi-Quellcode:
var
  TypeInfo: PTypeInfo;
  TypeData: PTypeData;
  V: Integer;
begin
  Assert(SizeOf(V) >= SizeOf(T));
  TypeInfo := System.TypeInfo(T);
  Assert(Assigned(TypeInfo) and (TypeInfo^.Kind = tkEnumeration));
  TypeData := System.TypInfo.GetTypeData(TypeInfo);
  V := 0;
  Move(Value, V, SizeOf(T));
  Assert((V >= TypeData^.MinValue) and (V <= TypeData^.MaxValue));

Glados 23. Aug 2017 22:43

AW: Enum-Typ als Parameter übergeben und mit einer Schleife durchgehen
 
Die Funktionen habe ich alle schon :P Aber ich weiß halt nicht wie ich durch die Schleife iterieren kann.
GetNames hab ich nicht.

Zacherl 23. Aug 2017 22:46

AW: Enum-Typ als Parameter übergeben und mit einer Schleife durchgehen
 
Zitat:

Zitat von Glados (Beitrag 1379317)
Die Funktionen habe ich alle schon :P Aber ich weiß halt nicht wie ich durch die Schleife iterieren kann.

Schau mal in meinen Edit.

Im Grunde hast du allerdings nur die Möglichkeit über die Ordinalwerte zu iterieren und dann ggfls. wieder in den expliziten Typ zu hardcasten.

Glados 23. Aug 2017 22:48

AW: Enum-Typ als Parameter übergeben und mit einer Schleife durchgehen
 
Das sieht super kompliziert aus und ich verstehe das nicht.
Zitat:

Im Grunde hast du allerdings nur die Möglichkeit über die Ordinalwerte zu iterieren und dann ggfls. wieder in den expliziten Typ zu hardcasten.
Das würde mir schon reichen. Denn mit einer anderen Funktion könnte ich dann anhand des Ordinalwerts den String bekommen.
Wie sähe das denn aus mit dem Ordinalwert? Meins oben funktioniert ja leider nicht.

Also im Grunde möchte ich meiner Funktion mehrere Enum-Typen übergeben können ("MeinEnum",... NICHT MeinEnum.XYZ)

Zacherl 23. Aug 2017 23:20

AW: Enum-Typ als Parameter übergeben und mit einer Schleife durchgehen
 
So in der Art vielleicht:
Delphi-Quellcode:
procedure TForm1.Test<T>;
var
  TypeInfo: PTypeInfo;
  TypeData: PTypeData;
  I: Integer;
  V: T;
begin
  TypeInfo := System.TypeInfo(T);
  Assert(Assigned(TypeInfo) and (TypeInfo^.Kind = tkEnumeration));
  TypeData := System.TypInfo.GetTypeData(TypeInfo);
  for I := TypeData^.MinValue to TypeData^.MaxValue do
  begin
    Move(I, V, SizeOf(T));
    ShowMessage(TRttiEnumerationType.GetName<T>(V));
  end;
end;
bzw.
Delphi-Quellcode:
procedure TForm1.Test<T>;
var
  TypeInfo: PTypeInfo;
  TypeData: PTypeData;
  I: Integer;
  V: T absolute I;
begin
  TypeInfo := System.TypeInfo(T);
  Assert(Assigned(TypeInfo) and (TypeInfo^.Kind = tkEnumeration));
  TypeData := System.TypInfo.GetTypeData(TypeInfo);
  for I := TypeData^.MinValue to TypeData^.MaxValue do
  begin
    ShowMessage(TRttiEnumerationType.GetName<T>(V));
  end;
end;
Da gibt es aber noch diverse Fallstricke glaube ich.


Alle Zeitangaben in WEZ +1. Es ist jetzt 07:55 Uhr.
Seite 1 von 2  1 2      

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