arrays - Delphi - 指向TRecord的const数组?
问题描述
如何让变量指向记录数组?
注意:我希望将 TRecord 的预定义数组作为常量......但是在代码中,我需要变量“W”来记录要使用的记录数组。
请注意,我不希望使用 TRecord 的构造函数在代码中(动态)创建 TRecord 数组,但希望拥有静态数组(因为数据不会改变)。
如何获取变量“W”来“记录”哪个 TRecord 数组?
请参阅下面的代码 - 更容易理解我的意思。
procedure TForm1.Button1Click(Sender: TObject);
type
TTestRec = record
X: string;
Y: Integer;
end;
TMyArr = TArray<TTestRec>;
const
ARRAY_A : TArray<string> = ['A1', 'A2', 'A3', 'A4'];
ARRAY_B : TArray<string> = ['B1', 'B2', 'B3'];
ARRAY_C : array[1..2] of TTestRec = (
(X: 'testC1'; Y:1),
(X: 'testC2'; Y:2)
);
ARRAY_D : array[1..3] of TTestRec = (
(X: 'testD1'; Y:3),
(X: 'testD2'; Y:4)
(X: 'testD3'; Y:9)
);
var
Z : TArray<string>;
W : array of TTestRec;
begin
Z := ARRAY_A; // this works
Z := ARRAY_B; // this works
W := ARRAY_C; // this does not work
W := ARRAY_D; // this does not work
end;
解决方案
分配ARRAY_A
orARRAY_B
有效Z
,因为您将TArray<string>
常量分配给TArray<string>
变量。它们都是同一类型,因此它们相互兼容。
分配ARRAY_C
or ARRAY_D
toW
不起作用,因为您将静态数组常量分配给动态数组变量。它们是彼此不兼容的不同类型,如 Delphi 的文档中所述:
类型兼容性
每种类型都与自身兼容。如果两种不同的类型至少满足以下条件之一,则它们是兼容的。
- 他们都是真正的类型。
- 它们都是整数类型。
- 一种类型是另一种类型的子范围。
- 两种类型都是相同类型的子范围。
- 两者都是具有兼容基本类型的集合类型。
- 两者都是具有相同字符数的压缩字符串类型。
- 一种是字符串类型,另一种是字符串、压缩字符串或
Char
类型。- 一种类型是
Variant
整数、实数、字符串、字符或布尔类型。- 两者都是类、类引用或接口类型,一种类型派生自另一种类型。
- 一种是
PAnsiChar
orPWideChar
,另一种是形式为 or 的从零开始的字符array[0..n] of PAnsiChar
数组PWideChar
。- 一种类型是
Pointer
(无类型指针),另一种是任何指针类型。- 两种类型都是(类型化的)指向同一类型的指针,并且
{$T+}
编译器指令有效。- 两者都是过程类型,具有相同的结果类型、相同数量的参数以及对应位置的参数之间的类型标识。
分配兼容性
分配兼容性不是对称关系。如果表达式的值落在 T1 的范围内并且至少满足以下条件之一,则可以将 T2 类型的表达式分配给 T1 类型的变量:
- T1和T2属于同一类型,不是包含任何级别的文件类型的文件类型或结构化类型。
- T1 和 T2 是兼容的序数类型。
- T1 和 T2 都是实数类型。
- T1 是实数类型,T2 是整数类型。
- T1 是
PAnsiChar
、或任何字符串类型PWideChar
,PChar
并且表达式是字符串常量。- T1 和 T2 都是字符串类型。
- T1 是字符串类型,T2 是
Char
压缩字符串类型。- T1 是一个长字符串,T2 是
PAnsiChar
,PWideChar
或PChar
。- T1 和 T2 是兼容的打包字符串类型。
- T1 和 T2 是兼容的集合类型。
- T1 和 T2 是兼容的指针类型。
- T1 和 T2 都是类、类引用或接口类型,而 T2 是从 T1 派生的。
- T1 是接口类型,T2 是实现 T1 的类类型。
- T1 是
PAnsiChar
orPWideChar
并且 T2 是一个从零开始的字符数组,其形式为array[0..n] of Char
(当 T1 为 时PAnsiChar
)或WideChar
(当 T1 为 时PWideChar
)。- T1 和 T2 是兼容的过程类型。(在某些赋值语句中,函数或过程标识符被视为过程类型的表达式。参见本章前面的“语句和表达式中的过程类型”。)
- T1
Variant
和 T2 是整数、实数、字符串、字符、布尔值、接口类型或OleVariant
类型。- T1 是一个
OleVariant
,T2 是一个整数、实数、字符串、字符、布尔值、接口或Variant
类型。- T1 是整数、实数、字符串、字符或布尔类型,T2 是
Variant
或OleVariant
。- T1 是
IUnknown
orIDispatch
接口类型,T2 是Variant
orOleVariant
。(如果 T1 是,或者如果T1 是 ,则变体的类型代码必须是varEmpty
、或。)varUnknown
varDispatch
IUnknown
varEmpty
varDispatch
IDispatch
分配ARRAY_A
或ARRAY_B
满足Z
“分配兼容性”要求。分配ARRAY_C
或ARRAY_D
分配W
不。
要解决静态数组的问题,您必须改用指针(动态数组已经是指针),例如:
procedure TForm1.Button1Click(Sender: TObject);
type
TTestRec = record
X: string;
Y: Integer;
end;
PTestRec = ^TTestRec;
const
ARRAY_A : TArray<string> = ['A1', 'A2', 'A3', 'A4'];
ARRAY_B : TArray<string> = ['B1', 'B2', 'B3'];
ARRAY_C : array[1..2] of TTestRec = (
(X: 'testC1'; Y:1),
(X: 'testC2'; Y:2)
);
ARRAY_D : array[1..3] of TTestRec = (
(X: 'testD1'; Y:3),
(X: 'testD2'; Y:4)
(X: 'testD3'; Y:9)
);
var
Z : TArray<string>;
W : PTestRec;
begin
Z := ARRAY_A;
Z := ARRAY_B;
W := @ARRAY_C[1];
W := @ARRAY_D[1];
end;
但是请注意,无法从W
自身确定它是指向 anarray[1..2] of TTestRec
还是 an array[1..3] of TTestRec
,这是两种完全不同的类型。因此,如果您需要使用W
来迭代数组,则必须单独跟踪可接受的边界,例如:
{$POINTERMATH ON}
procedure TForm1.Button1Click(Sender: TObject);
type
TTestRec = record
X: string;
Y: Integer;
end;
PTestRec = ^TTestRec;
const
ARRAY_A : TArray<string> = ['A1', 'A2', 'A3', 'A4'];
ARRAY_B : TArray<string> = ['B1', 'B2', 'B3'];
ARRAY_C : array[1..2] of TTestRec = (
(X: 'testC1'; Y:1),
(X: 'testC2'; Y:2)
);
ARRAY_D : array[1..3] of TTestRec = (
(X: 'testD1'; Y:3),
(X: 'testD2'; Y:4)
(X: 'testD3'; Y:9)
);
var
Z : TArray<string>;
W : PTestRec;
W_Len, I: Integer;
begin
Z := ARRAY_A;
for I := 0 to High(Z) do begin
// use Z[I] as needed ...
end;
Z := ARRAY_B;
for I := 0 to High(Z) do begin
// use Z[I] as needed ...
end;
W := @ARRAY_C[1];
W_Len := Length(ARRAY_C);
for I := 0 to Pred(W_Len) do begin
// use W[I] as needed ...
end;
W := @ARRAY_D[1];
W_Len := Length(ARRAY_D);
for I := 0 to Pred(W_Len) do begin
// use W[I] as needed ...
end;
end;
推荐阅读
- javascript - 猴子补丁 XMLHttpRequest.send 用于特殊 url
- amazon-web-services - 用于管理无 AWS 服务器的基础设施的 Terraform 或云形成
- python - 如何在 Django 中对空白字段表单进行单元测试?
- flutter - 消费者完成构建后颤振 showDialog
- jmeter - 将变量从一个 jdbc 请求发送到 JMeter 中的另一个 jdbc 请求
- grails - 创建名为 samlAuthenticationProvider 的 bean 时出错?
- python - 在 JSON 中转换 Python 列表
- java - 如何使用 querydsl 获取子字段?
- apache-spark - Spark Streaming 窗口使用
- python - gmpy2中如何准确判断一个mpfr数是否为整数?