- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我知道 array of const
被“翻译”为array of TVarRec
由编译器所以我想知道是否有一种方法可以直接存储开放数组的副本(或者可能使用 const
的引用),我的意思是无需创建循环将每个项目从 const 数组复制到TArray<TVarRec>
。以下代码显示了我正在尝试执行的操作。
TAppMessage = class
private
FMessage: string;
FArgs: TArray<TVarRec>;
public
constructor Create(AMessage: string; Args array of const);
function ToString: string;
end;
constructor TAppMessage.Create(AMessage: string; Args array of const);
begin
Self.FMessage := AMessage;
Self.FArgs := Args; //<-- E2010 Incompatible types: 'System.TArray<System.TVarRec>' and 'array of TVarRec'
end;
function TAppMessage.ToString: string;
begin
Result := Format(Self.FMessage, Self.FArgs);
end;
var AppMsg: TAppMessage;
AppMsg := TAppMessage.Create('A number %d and a text %s', [10, 'foo']);
ShowMessage(AppMsg.ToString);
有没有办法将一个常量开放数组分配给 TArray<TVarRec>
?
注意:我使用的是 Delphi 10.2.3(东京)
最佳答案
我
看到
已经看到几个建议您复制TVarRec
的答案s一一变成TArray<TVarRec>
。 这还不够!
它将适用于可以直接存储在 TVarRec
中的值。 ,例如Integer
s,但它不适用于不适合的值。它们在堆栈上分配(换句话说:在临时存储中),然后从 TVarRec
引用。 。看看TVarRec
的声明:
type
TVarRec = record { do not pack this record; it is compiler-generated }
case Integer of
0: (case Byte of
vtInteger: (VInteger: Integer);
vtBoolean: (VBoolean: Boolean);
vtChar: (VChar: _AnsiChr);
vtExtended: (VExtended: PExtended);
{$IFNDEF NEXTGEN}
vtString: (VString: _PShortStr);
{$ENDIF !NEXTGEN}
vtPointer: (VPointer: Pointer);
vtPChar: (VPChar: _PAnsiChr);
{$IFDEF AUTOREFCOUNT}
vtObject: (VObject: Pointer);
{$ELSE}
vtObject: (VObject: TObject);
{$ENDIF}
vtClass: (VClass: TClass);
vtWideChar: (VWideChar: WideChar);
vtPWideChar: (VPWideChar: PWideChar);
vtAnsiString: (VAnsiString: Pointer);
vtCurrency: (VCurrency: PCurrency);
vtVariant: (VVariant: PVariant);
vtInterface: (VInterface: Pointer);
vtWideString: (VWideString: Pointer);
vtInt64: (VInt64: PInt64);
vtUnicodeString: (VUnicodeString: Pointer);
);
1: (_Reserved1: NativeInt;
VType: Byte;
);
end;
如您所见,类型如 Currency
, Variant
或ShortString
显然不适合 TVarRec
,因此它们被引用(并且真实值由运行时放在堆栈上)。如果您只复制 TVarRec
s,您不复制这些值,并且由于这些值仅在调用期间有效,因此该引用将一旦例程结束就无效。因此,您必须将这些引用值复制到您自己的存储中,例如:
SetLength(Copies, Length(Values));
for I := 0 to High(Values) do
begin
Copies[I] := TVarRec(Values[I]);
case TVarRec(Values[I]).VType of
...
vtExtended:
begin
// Copy the referenced Extended to the heap:
New(Copies[I].VExtended);
Copies[I].VExtended^ := TVarRec(Values[I]).VExtended^;
end;
// etc...
等等...您还必须注意 UnicodeString
的正确重新计数s,AnsiString
s,Variant
s、接口(interface)等
所以不要听从那些告诉你复制数组的人的建议!
您必须真正进行深层复制,如我所示in an article I have written exactly about this 。我无法引用整篇文章,但您可以在我的网站上找到它。
不要只复制代码,还要阅读本节的其余部分,因为您必须在使用后释放复制数组引用的值,使用此处显示的函数。
关于delphi - 如何在 Delphi 中将常量开放数组分配给 TArray<TVarRec>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53037121/
我想使用具有多种类型的开放数组(例如:['string',12,123.21])。在我的搜索过程中,我发现了两种方法可以做到这一点。一种是使用 TVarRec 数组,另一种是使用 varArray。我
我想定义一个可以在 TClientDataSet SetRange 方法中进一步使用的 var 或 const: var lRangeStart : array of TVarRec; lRa
是否有在 TVarRec 和 Variant 值之间进行转换的标准方法? 我想解析“常量数组”并使用这些值来填充 TMSQuery 中的参数。为此,我使用列名称列表(从 TMSQuery.KeyFie
我知道 array of const被“翻译”为array of TVarRec由编译器所以我想知道是否有一种方法可以直接存储开放数组的副本(或者可能使用 const 的引用),我的意思是无需创建循环
我正在为存储库构建 SQL 查询生成器。此构建器将查找查询的所有必填字段并创建 SQL 文本。为此,我正在使用 Format() 过程。但是,我无法在运行时创建必须传递给 Format 过程的 TVa
我想将格式化参数 Args 传递到 Format功能。我找到了一些例子,但我找不到如何在 TVarRec 中分配字符串常量成员。以下代码编译失败,并显示 E2089 Invalid typecast。
我是一名优秀的程序员,十分优秀!