I'm trying to write a generic cached property accessor like the following but am getting a compiler error when trying to check whether the storage variable already contains a value:
function TMyClass.GetProp<T>(var ADataValue: T; const ARetriever: TFunc<T>): T;
begin
if ADataValue = Default(T) then // <-- compiler error on this line
ADataValue := ARetriever();
Result := ADataValue;
end;
The error I'm getting is "E2015 Operator not applicable to this operand type".
Would I have to put a constraint on T to make this work? The help file says that Default() would accept anything except generic types. In my case I'm dealing mostly with simple types like String, Integer and TDateTime.
Or is there some other library function to perform this particular check?
I'm using Delphi 2009 in case that matters.
P.S.: Just in case it isn't clear from the code what I'm trying to do: In my case determining the actual property values might take a while for various reasons and sometimes I might not even need them at all. On the plus side however the values are constant so I only want to call the code that determines the actual value the first time that property is accessed and then store the value in a class field and the next time that property is accessed return the cached value directly. Here's an example of how I hoped I would be able to use that code:
type
TMyClass = class
private
FSomeProp: String;
function GetSomeProp: String;
function GetProp<T>(var ADataValue: T; const ARetriever: TFunc<T>): T;
public
property SomeProp read GetSomeProp;
end;
function GetSomeProp: String;
begin
Result := GetProp<String>(FSomeProp,
function: String
begin
Result := SomeSlowOrExpensiveCalculation;
end);
end;
(obviously, there's more than just one property)
After a hint in the comments from Binis and digging around a little in Generics.Collections I came up with the following which appears to work just as I wanted it:
function TMyClass.GetProp<T>(var ADataValue: T; const ARetriever: TFunc<T>): T;
var
lComparer: IEqualityComparer<T>;
begin
lComparer := TEqualityComparer<T>.Default;
if lComparer.Equals(ADataValue, Default(T)) then
ADataValue := ARetriever();
Result := ADataValue;
end;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With