Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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)

like image 758
Oliver Giesen Avatar asked Nov 23 '09 10:11

Oliver Giesen


1 Answers

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;
like image 121
Oliver Giesen Avatar answered Oct 15 '22 21:10

Oliver Giesen