如何在Delphi中测试与Default(T)相等的泛型类型变量? [英] How do I test a generic type variable for equality with Default(T) in Delphi?

查看:739
本文介绍了如何在Delphi中测试与Default(T)相等的泛型类型变量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试编写一个通用的缓存属性访问器,如下所示,但是当尝试检查存储变量是否已经包含值时,我收到编译器错误:

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;

我得到的错误是E2015操作符不适用于此操作数类型。

The error I'm getting is "E2015 Operator not applicable to this operand type".

我必须对 T 设置约束才能使其工作吗?帮助文件说, Default()将接受除通用类型之外的任何内容。在我的情况下,我主要处理简单的类型,如 String 整数 TDateTime

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?

我正在使用Delphi 2009,以防万一重要。

I'm using Delphi 2009 in case that matters.

PS:为了防止代码不清楚我想做什么:在我的情况下,由于各种原因确定实际的财产价值可能需要一段时间,有时甚至根本不需要它们。然而,在正面方面,值是不变的,所以我只想调用第一次访问该属性时确定实际值的代码,然后将该值存储在一个类字段中,下一次访问该属性时返回缓存值直。以下是我希望能够使用该代码的示例:

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)

推荐答案

在Binis的评论中提到了一些关于Genericics.Collections的一些小提示后,我想出了以下这样的工作,就像我想要的那样:

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;

这篇关于如何在Delphi中测试与Default(T)相等的泛型类型变量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆