我需要将存储在字节数组中的数据移动到位于TList中的一组记录中,但是我收到此错误
E2197常量对象不能作为var参数传递
此代码重现了该问题。
uses
System.Generics.Collections,
System.SysUtils;
type
TData = record
Age : Byte;
Id : Integer;
end;
//this code is only to show the issue, for simplicity i'm filling only the first
//element of the TList but the real code needs fill N elements from a very big array.
var
List : TList<TData>;
P : array [0..1023] of byte;
begin
try
List:=TList<TData>.Create;
try
List.Count:=1;
//here i want to move the content of the P variable to the element 0
Move(P[0],List[0], SizeOf(TData));
finally
List.Free;
end;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
如何将缓冲区的内容复制到TList元素
答案 0 :(得分:4)
在XE2中,TList<T>
的内部存储是不透明和隐藏的。您无法通过正常方式访问它。将复制对列表元素的所有访问 - 对底层存储的引用不可用。所以你不能使用Move
对它进行blit。如果你想要一个可以blit的结构,你应该考虑一个动态数组TArray<T>
。
您总是可以使用实现TList<TData>
的类助手的技巧来公开私有变量FItems
。这非常hacky但会做你要求的。
type
__TListTData = TList<TData>;
//defeat E2086 Type 'TList<T>' is not yet completely defined
type
TListTDataHelper = class helper for TList<TData>
procedure Blit(const Source; Count: Integer);
end;
procedure TListTDataHelper.Blit(const Source; Count: Integer);
begin
System.Move(Source, Pointer(FItems)^, Count*SizeOf(Self[0]));
end;
我想您可能想在TListTDataHelper.Blit
中进行一些参数检查,但我会留给您。
如果您使用的是XE3,则可以使用List
属性访问TList<T>
的私有存储空间。
Move(P, Pointer(List.List)^, N*SizeOf(List[0]));
如果你不需要blit并且可以使用for循环,那么就这样做:
type
PData = ^TData;
var
i: Integer;
Ptr: PData;
....
List.Count := N;
Ptr := PData(@P);
for i := 0 to List.Count-1 do
begin
List[i] := Ptr^;
inc(Ptr);
end;
但我解释你的问题,你希望避免这个选项。
答案 1 :(得分:1)
不要使用Move()
,而是尝试使用TList<T>.Items[]
属性setter,让编译器和RTL为您处理复制:
type
PData = ^TData;
...
List[0] := PData(@P[0])^;