我有一个对象,唯一的责任就是保持价值。这个值可以直接通过构造函数传递,或者构造函数可以使用匿名函数告诉对象如何获取值。
type
TDefineCached<T> = Reference to function: T;
TValue<T> = class(TInterfacedObject, IValue<T>)
private
FValue: T;
FActive: Boolean;
FDefine: TDefineCached<T>;
procedure DoDefine;
public
constructor Create(const Define: TDefineCached<T>);
class function New(const Define: TDefineCached<T>): IValue<T>; overload;
class function New(const Value: T): IValue<T>; overload;
function Value: T;
end;
该匿名函数将仅在第一次需要该值时执行,然后该值将被缓存以在进一步调用中返回。 除了一种情况外,这种情况正如预期的那样起作用,如下所述:
private
FCoordinate: IValue<Double>;
// some other code
function TGeoCoordinate.ToStringValue: IValue<string>;
var
s: string;
begin
s := FCoordinate.Value.ToString;
Result := TValue<string>.New(s);
end;
此代码将按预期完美地运行。
由于FCoordinate本身是IValue,FCoordinate.Value
将返回Double原语。因此,当与D10的本地记录助手结合使用时,FCoordinate.Value.ToString
将返回s
将保留的原始字符串。
然后,TValue<string>.New
的一个重载将接受一个原始字符串值,s
就在那个小巷里。
一切都很好。
但是,s
变量是或应该是可选的。它只会被使用一次,所以我们可以(应该)用表达式本身替换它。
但是当我这样做时:
function TGeoCoordinate.ToStringValue: IValue<string>;
begin
Result := TValue<string>.New(FCoordinate.Value.ToString);
end;
编译器将返回[dcc32 Error] E2250 There is no overloaded version of 'New' that can be called with these arguments
。
在尝试检测问题时,我注意到这也可以正常工作:
function TGeoCoordinate.ToStringValue: IValue<string>;
begin
Result := TValue<string>.New((FCoordinate.Value.ToString));
end;
在表达式中添加额外的一对parentesis将强制它评估完整表达式FCoordinate.Value.ToString
,并且TValue.New将不再失败。
尽管如此,我确实认为这不是必要的。
然后我尝试创建另一个IValue实现,其中类函数New没有重载,只接受T值,这也可以正常工作,这意味着编译器被重载版本{{1接受匿名函数。
这可能是编译器错误,还是我错过了这张图片中的内容?
我试图搜索类似的问题,但是对于任何可以过滤它的搜索字词都没有问题,因为这个问题使用了相当普遍的措辞。