PiedSoftware 3 Posted April 1, 2022 (edited) Hi I have been using a generic record to convert combo-boxes to enumerated type. But Delphi spits the dummy if the type has any numbers specified. For example with this code the compiler throws up the error message "E2134 Type 'TDDArrangementId' has no type info. In the generic type TypeInfo(T) returns nil. type TDDArrangementId = (daOutstanding = 1, daWeeklyGap, daAmount, daGapAmount); ... procedure Test; var ti: PTypeInfo; begin ti := TypeInfo(TDDArrangementId); But removing the " = 1" makes it all build and run just fine. Can anyone confirm that Delphi's rtti system simply does not handle enumerated types if they are not zero-based? I'm using 10.4 --- Mark Edited April 1, 2022 by PiedSoftware Share this post Link to post
sakura 45 Posted April 1, 2022 14 minutes ago, PiedSoftware said: Can anyone confirm that Delphi's rtti system simply does not handle enumerated types if they are not zero-based? Saly: yes, that's the case. Share this post Link to post
Fr0sT.Brutal 900 Posted April 1, 2022 Yes. The only solution is to start the enum from 0 (why using 1 as starting value?) Share this post Link to post
Uwe Raabe 2056 Posted April 1, 2022 My approach to these types of problems is to add a record helper for the enumeration that handles the conversion from and to Integer. type TDDArrangementId = (daOutstanding, daWeeklyGap, daAmount, daGapAmount); TDDArrangementIdHelper = record helper for TDDArrangementId private function GetAsInteger: Integer; procedure SetAsInteger(const Value: Integer); public property AsInteger: Integer read GetAsInteger write SetAsInteger; end; function TDDArrangementIdHelper.GetAsInteger: Integer; begin Result := Ord(Succ(Self)); end; procedure TDDArrangementIdHelper.SetAsInteger(const Value: Integer); begin Self := TDDArrangementId(Pred(Value)); end; The usage would then look like this: var myVar: TDDArrangementId; begin myVar.AsInteger := 1; Assert(myVar = daOutstanding); Inc(myVar); Assert(myVar = daWeeklyGap); Assert(myVar.AsInteger = 2); end. 2 Share this post Link to post
PiedSoftware 3 Posted April 4, 2022 On 4/1/2022 at 4:56 PM, Fr0sT.Brutal said: Yes. The only solution is to start the enum from 0 (why using 1 as starting value?) The values correspond with values on a database. Share this post Link to post
PiedSoftware 3 Posted April 4, 2022 On 4/1/2022 at 8:01 PM, Uwe Raabe said: My approach to these types of problems is to add a record helper for the enumeration that handles the conversion from and to Integer. Thanks. That would be useful. I have decided to do it differently in this case Share this post Link to post
Fr0sT.Brutal 900 Posted April 4, 2022 2 hours ago, PiedSoftware said: The values correspond with values on a database. You may use the following trick which I recently invented and applied to all my projects: 1) TEnumNullable = (enNone, enFoo, enBar); 2) TEnum = enFoo..enBar; // or Succ(Low(TEnumNullable))..High(TEnumNullable) this has following benefits: - RTTI features - "Null" value that won't cause range check errors in FPC like usual TEnum(-1) - "Null" value that is NULL (zero) actually - ZeroMemory, Default(), Class.Create init fields with this value - two types so you can differentiate where null is expected and where not - simple and obvious DB_Value_Of_Enum = Ord() 1 Share this post Link to post