【发布时间】:2021-10-28 10:23:29
【问题描述】:
我正在尝试有条件地分配一个本地开放数组变量,以便它指向一个 const 开放数组参数:
uses
System.Generics.Collections,
System.Generics.Defaults;
type
TArray = class(System.Generics.Collections.TArray)
public
class function SameValues<T>(const AValuesA: array of T; AValuesB: array of T; const AComparer: IEqualityComparer<T>; AOrderMatters : Boolean = True) : Boolean; overload; static;
end;
...
class function TArray.SameValues<T>(const AValuesA: array of T; AValuesB: array of T; const AComparer: IEqualityComparer<T>; AOrderMatters : Boolean = True) : Boolean;
var
ArrA : TArray<T>;
ArrB : TArray<T>;
i : integer;
begin
//checking sizes
if(Length(AValuesA) <> Length(AValuesB)) then
begin
Result := False;
Exit;
end;
if(AOrderMatters) then
begin
//I don't need to change the arrays, so I could directly point to the open array parameters
ArrA := AValuesA;
ArrB := AValuesB;
end else
begin
//copying to local arrays
SetLength(ArrA, Length(AValuesA));
TArray.Copy<T>(AValuesA, ArrA, Length(AValuesA));
SetLength(ArrB, Length(AValuesB));
TArray.Copy<T>(AValuesB, ArrB, Length(AValuesB));
//sorting local arrays
TArray.Sort<T>(ArrA);
TArray.Sort<T>(ArrB);
end;
//comparing elements
i := 0;
while(i < Length(ArrA)) do
begin
if(not AComparer.Equals(ArrA[i], ArrB[i])) then
begin
Result := False;
Exit;
end;
Inc(i);
end;
Result := True;
end;
在编译时,它会在以下位置引发 E2010 错误:
//I don't need to change the arrays, so I could directly point to the open array parameters
ArrA := AValuesA;
ArrB := AValuesB;
E2010 不兼容的类型:“动态数组”和“T 数组”
我尝试了以下方法:
ArrA := @AValuesA;
ArrB := @AValuesB;
它会编译,但会在运行时引发 AV 异常(最重要的是,我不知道这是否是一种安全的方法)。
这是我的测试应用程序代码:
uses
System.Generics.Defaults;
procedure TForm1.FormCreate(Sender: TObject);
var
ArrA : array of string;
ArrB : array of string;
begin
SetLength(ArrA, 2);
ArrA[0] := 'hello';
ArrA[1] := 'world';
SetLength(ArrB, 2);
ArrB[0] := 'world';
ArrB[1] := 'hello';
if(TArray.SameValues<string>(ArrA, ArrB, TEqualityComparer<string>.Default, True)) then
ShowMessage('Same values and same order')
else if(TArray.SameValues<string>(ArrA, ArrB, TEqualityComparer<string>.Default, False)) then
ShowMessage('Same values but different order')
else
ShowMessage('Different values');
end;
【问题讨论】:
-
你不能这样做,这些类型只是不兼容。动态数组的元数据(即引用计数和长度)是对象本身的一部分,但对于开放数组,其元数据(只是长度)作为单独的参数传递给函数。
-
哦!这太不舒服了!我会做两个分开的功能...谢谢
-
您可以在一个函数中轻松完成。您只需创建副本,对其进行排序,然后再次递归调用相同的函数,但将
True传递给AOrderMatters。我会写一个答案来说明如何。 -
是的,它肯定会是一个更简洁的代码,但我担心性能问题,如果不是绝对必要的话,我会尽量避免复制整个数组
-
如果要排序,则必须复制数组,但如果不需要排序,则可以按照我的描述避免复制,正如我的回答所表明的那样。
标签: arrays delphi delphi-xe7