How do I test a generic type variable for equality with Default(T) in Delphi?

caching, default-value, delphi, generics

Solution

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;

Problem

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)

Original source