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 o开发者_如何学Gof 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;
The problem is not the Default function, but the equality operator =.
You could constrain T to IEquatable and use the Equals method like this:
TMyClass = class
function GetProp<T : IEquatable<T>>(var ADataValue: T; const ARetriever:
end;
...
function TMyClass.GetProp<T>(var ADataValue: T; const ARetriever: TFunc<T>): T;
begin
if ADataValue.Equals (Default(T)) then
ADataValue := ARetriever();
Result := ADataValue;
end;
加载中,请稍侯......
精彩评论