使用枚举类型访问动态数组
Access dynamic array with enumeration type
我处理我们软件的标准数据 class。这是当前状态的最小示例:
TDataOne = (Width, Length, Height);
TDataTwo = (Diameter, Weight);
TDatStruct = class;
TDatSubStructOne = class(TDatStruct)
public
myData : array[TDataOne] of double;
procedure writeToFile(AFileName : string);
end;
TDatSubStructTwo = class(TDatStruct)
public
myData : array[TDataTwo] of double;
procedure writeToFile(AFileName : string);
end;
为了减少代码冗余我想在TDatStruct
中构思一个通用写函数的数据结构。挑战(至少对我这个业余爱好者来说)是:
mydata
大小可变,具体取决于子结构和基于不同枚举类型的基础
- 我仍然想在子结构中使用枚举类型访问
mydata
- 由于实际代码中不同数组的数量,我不想将子结构数据作为参数传递给公共写入函数
我唯一的想法(忽略点3)是将子结构的数组数据作为开放数组参数传递给公共写入过程,如:
writeToFile(AFileName : string; writeData : array of double);
有什么方法可以将动态数组与枚举类型或虚拟枚举数组结合起来吗?还是我完全走错了路?
mydata is of variable size depending on the substruct and bases on different enum types
Delphi 具有内在函数 Low and High
您不需要知道数组的大小。
I still want to access mydata with an enumerated type in the sub structs
使用 succ
和 pred
内部方法遍历枚举。
I do not want to pass the sub structure data as parameter to the common write function because of the number of different arrays in the real code
你所有的数组在我看来都一样...
它们只是 array of double
,尽管元素数量不同。
您可以像这样实现 writeToFile
:
procedure writeArrayToFile(const AFileName : string; const writeData : array of double);
var
i: integer;
begin
for i:= low(writeData) to High(writeData) do begin
WriteADoubleToFile(AFilename, writeData[i]);
end; {for i}
end;
注意 const
的使用,如果你不使用它,数组将被复制到堆栈,导致大数组的巨大延迟。
如果数组是你的 class 的数据成员,那么你可以像这样简单地编写代码:
procedure TDatStruct.writeToFile(const AFileName : string);
begin
WriteArrayToFile(FileName, GetMyData^);
end;
请注意,由于父级 class TDatStruct
内部实际上没有任何数据,因此您需要编写一个虚函数来获取该数据。
type
TMyArray = array[0..0] of double;
PMyArray = ^TMyArray;
.....
TDatStruct = class
protected
function GetMyData: PMyArray; virtual; abstract;
public
procedure WriteToFile(const Filename: string); //no need for virtual
end;
WriteArrayToFile
的 open array parameter 将为您解决问题。
注意 writeToFile
中的数组参数是一个 "open array parameter",这将接受静态和动态数组。
如果您使用不同类型的数组(double/string 等)。
然后使用通用方法。
Is there any way to combine a dynamic array with an enumerated type or a virtual enumerated array? Or am I completely on the wrong path?
动态数组的元素数量可变。
您不能直接使用枚举对其进行索引。
但是,您可以使用 Ord
内部函数将枚举值转换为整数。
它也适用于具有超过 256 个值的枚举。 文档不正确,它将根据需要 return 字节、单词或基数。
function FixedArrayToDynamicArray(const input: array of double): TArray<double>;
begin
//translate a fixed array to a dynamic array.
SetLength(Result, High(input));
Move(input[0], Result[0], SizeOf(Double) * High(input));
end;
pre-generics 代码变为:
type
TDoubleArray = array of double;
function FixedArrayToDynamicArray(const input: array of double): TDoubleArray;
... same from here on.
有许多不同的方法,很难说哪种方法最适合您的情况。
当然,WriteToFile
应该作为摘要在TDatStruct
中引入:
TDatStruct = class
public
procedure WriteToFile(AFileName: string); virtual; abstract;
后代应该以不同的方式实现它:
TDatStructOne = class (TDatStruct)
...
public
procedure WriteToFile(AFileName: string); override;
通过这种方式,你可以得到 class TDatStruct 的对象,它实际上可以是 TDatStructOne 或 TDatStructTwo,但是使用它的代码不需要 'know',它处理的内容:基本多态性。
在这种情况下,您可以自由选择用于在每个 class 中存储信息的数据类型,实现可能会有所不同。最简单的是:
TDatStructOne = class (TDatStruct)
public
Width: Double;
Length: Double;
Height: Double;
procedure WriteToFile(AFileName: string); override;
end;
TDatStructTwo = class (TDatStruct)
public
Diameter: Double;
Weight: Double;
procedure WriteToFile(AFileName: string); override;
end;
并且在WriteToFile
中每个后代都各司其职。
所以,通过你的挑战:
- 你将拥有可变大小的数据,不一定是双精度数组,任何你想要的(字符串、整数、集合等)
- 只要您拥有 class TDatStructOne 或 TDatStructTwo(具体 classes)
的对象,您就可以方便地访问所有这些字段
- 没有所谓的通用写程序。相反,你有共同点 "write interface"。你写
obj.SaveToFile(FileName)
,它会相应地被保存。
我处理我们软件的标准数据 class。这是当前状态的最小示例:
TDataOne = (Width, Length, Height);
TDataTwo = (Diameter, Weight);
TDatStruct = class;
TDatSubStructOne = class(TDatStruct)
public
myData : array[TDataOne] of double;
procedure writeToFile(AFileName : string);
end;
TDatSubStructTwo = class(TDatStruct)
public
myData : array[TDataTwo] of double;
procedure writeToFile(AFileName : string);
end;
为了减少代码冗余我想在TDatStruct
中构思一个通用写函数的数据结构。挑战(至少对我这个业余爱好者来说)是:
mydata
大小可变,具体取决于子结构和基于不同枚举类型的基础- 我仍然想在子结构中使用枚举类型访问
mydata
- 由于实际代码中不同数组的数量,我不想将子结构数据作为参数传递给公共写入函数
我唯一的想法(忽略点3)是将子结构的数组数据作为开放数组参数传递给公共写入过程,如:
writeToFile(AFileName : string; writeData : array of double);
有什么方法可以将动态数组与枚举类型或虚拟枚举数组结合起来吗?还是我完全走错了路?
mydata is of variable size depending on the substruct and bases on different enum types
Delphi 具有内在函数 Low and High
您不需要知道数组的大小。
I still want to access mydata with an enumerated type in the sub structs
使用 succ
和 pred
内部方法遍历枚举。
I do not want to pass the sub structure data as parameter to the common write function because of the number of different arrays in the real code
你所有的数组在我看来都一样...
它们只是 array of double
,尽管元素数量不同。
您可以像这样实现 writeToFile
:
procedure writeArrayToFile(const AFileName : string; const writeData : array of double);
var
i: integer;
begin
for i:= low(writeData) to High(writeData) do begin
WriteADoubleToFile(AFilename, writeData[i]);
end; {for i}
end;
注意 const
的使用,如果你不使用它,数组将被复制到堆栈,导致大数组的巨大延迟。
如果数组是你的 class 的数据成员,那么你可以像这样简单地编写代码:
procedure TDatStruct.writeToFile(const AFileName : string);
begin
WriteArrayToFile(FileName, GetMyData^);
end;
请注意,由于父级 class TDatStruct
内部实际上没有任何数据,因此您需要编写一个虚函数来获取该数据。
type
TMyArray = array[0..0] of double;
PMyArray = ^TMyArray;
.....
TDatStruct = class
protected
function GetMyData: PMyArray; virtual; abstract;
public
procedure WriteToFile(const Filename: string); //no need for virtual
end;
WriteArrayToFile
的 open array parameter 将为您解决问题。
注意 writeToFile
中的数组参数是一个 "open array parameter",这将接受静态和动态数组。
如果您使用不同类型的数组(double/string 等)。
然后使用通用方法。
Is there any way to combine a dynamic array with an enumerated type or a virtual enumerated array? Or am I completely on the wrong path?
动态数组的元素数量可变。
您不能直接使用枚举对其进行索引。
但是,您可以使用 Ord
内部函数将枚举值转换为整数。
它也适用于具有超过 256 个值的枚举。 文档不正确,它将根据需要 return 字节、单词或基数。
function FixedArrayToDynamicArray(const input: array of double): TArray<double>;
begin
//translate a fixed array to a dynamic array.
SetLength(Result, High(input));
Move(input[0], Result[0], SizeOf(Double) * High(input));
end;
pre-generics 代码变为:
type
TDoubleArray = array of double;
function FixedArrayToDynamicArray(const input: array of double): TDoubleArray;
... same from here on.
有许多不同的方法,很难说哪种方法最适合您的情况。
当然,WriteToFile
应该作为摘要在TDatStruct
中引入:
TDatStruct = class
public
procedure WriteToFile(AFileName: string); virtual; abstract;
后代应该以不同的方式实现它:
TDatStructOne = class (TDatStruct)
...
public
procedure WriteToFile(AFileName: string); override;
通过这种方式,你可以得到 class TDatStruct 的对象,它实际上可以是 TDatStructOne 或 TDatStructTwo,但是使用它的代码不需要 'know',它处理的内容:基本多态性。
在这种情况下,您可以自由选择用于在每个 class 中存储信息的数据类型,实现可能会有所不同。最简单的是:
TDatStructOne = class (TDatStruct)
public
Width: Double;
Length: Double;
Height: Double;
procedure WriteToFile(AFileName: string); override;
end;
TDatStructTwo = class (TDatStruct)
public
Diameter: Double;
Weight: Double;
procedure WriteToFile(AFileName: string); override;
end;
并且在WriteToFile
中每个后代都各司其职。
所以,通过你的挑战:
- 你将拥有可变大小的数据,不一定是双精度数组,任何你想要的(字符串、整数、集合等)
- 只要您拥有 class TDatStructOne 或 TDatStructTwo(具体 classes) 的对象,您就可以方便地访问所有这些字段
- 没有所谓的通用写程序。相反,你有共同点 "write interface"。你写
obj.SaveToFile(FileName)
,它会相应地被保存。