Jacek Laskowski 57 Posted April 20, 2020 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
Vandrovnik 214 Posted April 20, 2020 (edited) 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 April 20, 2020 by Vandrovnik 2 Share this post Link to post
Jacek Laskowski 57 Posted April 20, 2020 Your code is identical to mine, don't I notice anything? I still get compilation error on Delphi 10.3 Share this post Link to post
Tommi Prami 130 Posted April 20, 2020 procedure SetFromVariant<T>(const aValue : Variant); procedure SetFromVariant(const aValue : Variant); Share this post Link to post
Jacek Laskowski 57 Posted April 20, 2020 11 minutes ago, Tommi Prami said: procedure SetFromVariant<T>(const aValue : Variant); procedure SetFromVariant(const aValue : Variant); I'm blind, sorry and thx! 🙂 1 Share this post Link to post
Remy Lebeau 1393 Posted April 20, 2020 (edited) 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 April 20, 2020 by Remy Lebeau Share this post Link to post
Jacek Laskowski 57 Posted April 21, 2020 @Remy Lebeau That's impossible, fData is generic: [dcc32 Error] E2010 Incompatible types: 'T' and 'Variant' Share this post Link to post
Remy Lebeau 1393 Posted April 21, 2020 @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
Jacek Laskowski 57 Posted April 22, 2020 @Remy Lebeau I cannot use this constraint because it blocks the use of string types (because it is not a valuable type). Share this post Link to post
Remy Lebeau 1393 Posted April 22, 2020 (edited) And this is why I HATE Generics! They cause more headaches than they solve. Edited April 22, 2020 by Remy Lebeau 1 Share this post Link to post
Georgge Bakh 29 Posted April 24, 2020 @Remy Lebeau Generics are OK. And very useful. But some implementations are not. 😉 Btw in FPC your code compiles and working properly. Share this post Link to post