7

次のような一般的なキャッシュ プロパティ アクセサーを記述しようとしていますが、ストレージ変数に既に値が含まれているかどうかを確認しようとすると、コンパイラ エラーが発生します。

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;

私が得ているエラーは、「E2015 演算子はこのオペランド タイプには適用できません」です。

これを機能させるには、制約を付ける必要がありTますか? ヘルプ ファイルには、Default()ジェネリック型以外は何でも受け入れると書かれています。私の場合、主にString、 、Integerなどの単純な型を扱っていTDateTimeます。

または、この特定のチェックを実行するための他のライブラリ関数がありますか?

問題が発生した場合に備えて、Delphi 2009 を使用しています。


PS:コードから何をしようとしているのかが明確でない場合に備えて:私の場合、実際のプロパティ値の決定にはさまざまな理由で時間がかかる場合があり、場合によってはそれらがまったく必要ない場合もあります。ただし、プラス面では、値は一定であるため、そのプロパティが最初にアクセスされたときに実際の値を決定するコードのみを呼び出し、その値をクラス フィールドに格納し、次にそのプロパティにアクセスしたときにキャッシュされた値を返します。直接。これは、そのコードを使用できるようになることを望んでいた方法の例です。

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;

(明らかに、プロパティは 1 つだけではありません)

4

2 に答える 2

12

Binis からのコメントにヒントがあり、Generics.Collections を少し掘り下げた後、次のように思いつきました。

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;
于 2009-11-23T21:59:16.800 に答える
0

問題はDefault関数ではなく、等価演算子=です。

次のようにメソッドを制約TIEquatableて使用できます。Equals

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;   
于 2009-11-23T11:10:08.617 に答える