TValue string<-->Boolean back and forth
Asked Answered
A

2

7

I'm playing arround with TValue

I've written this code in a blank project:

uses
  RTTI;

procedure TForm1.FormCreate(Sender: TObject);
var
  s: string;
  b: Boolean;
begin
  s := TValue.From<Boolean > (True).ToString;
  b := TValue.From<string > (s).AsType<Boolean>;
end;

But I can not convert back from string to boolean; I get an Invalid Typecast exception in the second line.

I'm using Delphi XE but it is the same result in Delphi Xe6 which leads me to the conclusion: I'm using TValue wrong.

So please what am I doing wrong.

Arnaud answered 13/1, 2015 at 8:55 Comment(1)
TValue.ToString() has specific knowledge of Boolean RTTI and knows to call GetEnumName() to convert such a value to a string. TValue.AsType(), on the other hand, does not define any String->Enum conversion (see the giant Conversions[][] array in System.Rtti.pas). It only supports Enum conversions when the source and dest types are the same enum type, or when both are Boolean types (they can be different byte sizes).Splasher
D
5

Although you give Boolean as the example in your question, I'm going to assume that you are really interested in the full generality of enumerated types. Otherwise you would just call StrToBool.

TValue is not designed to perform the conversion that you are attempting. Ultimately, at the low-level, the functions GetEnumValue and GetEnumName in the System.TypInfo unit are the functions that perform these conversions.

In modern versions of Delphi you can use TRttiEnumerationType to convert from text to an enumerated type value:

b := TRttiEnumerationType.GetValue<Boolean>(s);

You can move in the other direction like this:

s := TRttiEnumerationType.GetName<Boolean>(b);

These methods are implemented with calls to GetEnumValue and GetEnumName respectively.

Older versions of Delphi hide TRttiEnumerationType.GetValue and TRttiEnumerationType.GetName as private methods. If you are using such a version of Delphi then you should use GetEnumName.

Dallasdalli answered 13/1, 2015 at 8:59 Comment(5)
I'll try do that but TRttiEnumerationType.GetValue and GetName are both private. Så I think i'll have to go with GetEnumValueArnaud
Still I find i strange that I can not use TValueArnaud
They are public in the version of RTTI that I am looking at. You didn't add a version tag. However, I can see that you mention XE in the text. Yes, private thereDallasdalli
I would not use TValue at all here. It's massively bloated. I know @TLama suggested that but I would offer an alternative view. Indeed, I think that in your previous question, your code was needlessly complex because you were compelled to instantiate an object in order to perform a conversion. Generic static class methods are the way to go here.Dallasdalli
Note that TRttiEnumerationType.GetValuecan return -1. See comment on exception handling in a later answer https://mcmap.net/q/1480442/-delphi-invalid-enum-value-39-_24170-39Modillion
D
6

TValue is not meant to convert types that are not assignment compatible. It was designed to hold values while transporting them in the RTTI and to respect the assignment rules of Delphi.

Only ToString can output the value in some string representation but a type that you cannot simply assign a string to will also fail when doing that with TValue.

TValue is not a Variant.

If you want to convert a string to boolean and back then use StrToBool and BoolToStr.

Disconsolate answered 13/1, 2015 at 9:10 Comment(0)
D
5

Although you give Boolean as the example in your question, I'm going to assume that you are really interested in the full generality of enumerated types. Otherwise you would just call StrToBool.

TValue is not designed to perform the conversion that you are attempting. Ultimately, at the low-level, the functions GetEnumValue and GetEnumName in the System.TypInfo unit are the functions that perform these conversions.

In modern versions of Delphi you can use TRttiEnumerationType to convert from text to an enumerated type value:

b := TRttiEnumerationType.GetValue<Boolean>(s);

You can move in the other direction like this:

s := TRttiEnumerationType.GetName<Boolean>(b);

These methods are implemented with calls to GetEnumValue and GetEnumName respectively.

Older versions of Delphi hide TRttiEnumerationType.GetValue and TRttiEnumerationType.GetName as private methods. If you are using such a version of Delphi then you should use GetEnumName.

Dallasdalli answered 13/1, 2015 at 8:59 Comment(5)
I'll try do that but TRttiEnumerationType.GetValue and GetName are both private. Så I think i'll have to go with GetEnumValueArnaud
Still I find i strange that I can not use TValueArnaud
They are public in the version of RTTI that I am looking at. You didn't add a version tag. However, I can see that you mention XE in the text. Yes, private thereDallasdalli
I would not use TValue at all here. It's massively bloated. I know @TLama suggested that but I would offer an alternative view. Indeed, I think that in your previous question, your code was needlessly complex because you were compelled to instantiate an object in order to perform a conversion. Generic static class methods are the way to go here.Dallasdalli
Note that TRttiEnumerationType.GetValuecan return -1. See comment on exception handling in a later answer https://mcmap.net/q/1480442/-delphi-invalid-enum-value-39-_24170-39Modillion

© 2022 - 2024 — McMap. All rights reserved.