Jump to content
Jacek Laskowski

Variant to generic T, how?

Recommended Posts

How to set the generic class field to the value provided by Variant?

 

The following code is not compiled.

  ToField<T> = class
  private
    fData : T;
  protected
    procedure SetFromVariant<T>(const aValue : Variant);

 [...]


procedure ToField<T>.SetFromVariant<T>(const aValue : Variant);
var
  val: TValue;
begin
  val := TValue.FromVariant(aValue);
  fData := val.AsType<T>; <=== [dcc32 Error] E2008 Incompatible types

[dcc32 Error] E2008 Incompatible types

 

Share this post


Link to post

This compiles, but I have not tested, whether it works as expected 🙂


 

     ToField<T> = class(tObject)
      private
       fData : T;
      protected
       procedure SetFromVariant(const aValue : Variant);
     end;


procedure ToField<T>.SetFromVariant(const aValue: Variant);
 var val: TValue;
 begin
 val := TValue.FromVariant(aValue);
 fData := val.AsType<T>;
end;

 

Edited by Vandrovnik
  • Thanks 2

Share this post


Link to post
procedure SetFromVariant<T>(const aValue : Variant);
procedure SetFromVariant(const aValue : Variant);

Share this post


Link to post
11 minutes ago, Tommi Prami said:

procedure SetFromVariant<T>(const aValue : Variant);
procedure SetFromVariant(const aValue : Variant);

I'm blind, sorry and thx! 🙂

 

  • Like 1

Share this post


Link to post

Can't you just assign the Variant to the field directly and let the Variant handle the conversion?  Why do you need to go through TValue at all?

procedure ToField<T>.SetFromVariant(const aValue : Variant);
begin
  fData := aValue;
end;

Internally, when TValue is holding a Variant, TValue.AsType<T>() will look at the Variant's VType, copy the appropriate TVarData field to a temp TValue, and then assign that temp to the Result variable via TValue.Get<T>().  So just take out the middle man (TValue), Variant already knows how to do that same conversion directly.

Edited by Remy Lebeau

Share this post


Link to post

@Jacek Laskowski I can't test this myself (no working IDE), but what about if the 'record' constraint is added to the Generic so the compiler knows that T is a value type?

ToField<T: record> = class
private
  fData : T;
protected
  procedure SetFromVariant(const aValue : Variant);
end;

procedure ToField<T>.SetFromVariant(const aValue : Variant);
begin
  fData := aValue;
end;

 

Share this post


Link to post

And this is why I HATE Generics!  They cause more headaches than they solve.

Edited by Remy Lebeau
  • Haha 1

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×