gpt4 book ai didi

arrays - 如何在 Delphi 中公开私有(private)静态数组字段的内置枚举器?

转载 作者:行者123 更新时间:2023-12-03 15:46:35 25 4
gpt4 key购买 nike

我正在尝试公开 TEnumerator 中的私有(private)静态数组的构建。

Delphi 本身允许直接枚举静态数组(见下文),因此我怀疑 Delphi 在后台为静态数组创建一个枚举器,我希望能够在 GetEnumerator 方法中创建和公开相同的枚举器.

(我使用的是Delphi XE2)。

program Project6;

{$APPTYPE CONSOLE}

{$R *.res}

uses
System.SysUtils,
System.Generics.Collections;

type
TMyEnum = (meA, meB);

TMyClass = class
private
FItems: array[TMyEnum] of Integer;
protected
public
function GetEnumerator: TEnumerator<Integer>;
end;

{ TMyClass }

function TMyClass.GetEnumerator: TEnumerator<Integer>;
begin
// What is the simplies way of creating this enumerator?
end;

var
myObj: TMyClass;
i: Integer;

begin
myObj := TMyClass.Create;
try
// This works but only in the same unit
for i in myObj.FItems do
WriteLn(i);

for i in myObj do
WriteLn(i);

except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
ReadLn;
end.

请注意,我可以编写如下所示的自定义模拟器。但我试图避免这种情况并公开内置的。

TStaticArrayEnumerator<T> = class(TEnumerator<T>)
private
FCurrent: Pointer;
FElementAfterLast: Pointer;
protected
function DoGetCurrent: T; override;
function DoMoveNext: Boolean; override;
public
constructor Create(aArray: Pointer; aCount: Integer);
end;

{ TStaticArrayEnumerator<T> }

constructor TStaticArrayEnumerator<T>.Create(aArray: Pointer; aCount: Integer);
begin
// need to point Current before the first element (see comment in DoMoveNext)
FCurrent := Pointer(NativeInt(aArray) - SizeOf(T));
FElementSize := aElementSize;
FElementAfterLast := Pointer(NativeInt(aArray) + aCount * SizeOf(T))
end;

function TStaticArrayEnumerator<T>.DoGetCurrent: T;
begin
Result := T(FCurrent^);
end;

function TStaticArrayEnumerator<T>.DoMoveNext: Boolean;
begin
// This method gets called before DoGetCurrent gets called the first time
FCurrent := Pointer(NativeInt(FCurrent) + SizeOf(T));

Result := not (FCurrent = FElementAfterLast);
end;

最佳答案

Note that I can write a custom emulator like below. But I am trying to avoid this and expose the built in one.

你不能。没有表示数组枚举器的类型。当您在数组的元素上编写 for..in 循环时,编译器会通过内联经典的 for 循环来处理该问题。

考虑这个程序:

type
TMyEnum = (enum1, enum2, enum3);

var
arr: array [TMyEnum] of Integer;
i: Integer;

begin
for i in arr do
Writeln(i);
Readln;
end.

生成的代码:

Project1.dpr.13: for i in arr do004060D7 BE9CAB4000       mov esi,$0040ab9c004060DC 33DB             xor ebx,ebx004060DE 8B3C9E           mov edi,[esi+ebx*4]Project1.dpr.14: Writeln(i);004060E1 A110784000       mov eax,[$00407810]004060E6 8BD7             mov edx,edi004060E8 E823DCFFFF       call @Write0Long004060ED E8FEDEFFFF       call @WriteLn004060F2 E869CCFFFF       call @_IOTest004060F7 43               inc ebxProject1.dpr.13: for i in arr do004060F8 83FB03           cmp ebx,$03004060FB 75E1             jnz $004060deProject1.dpr.15: Readln;004060FD A114784000       mov eax,[$00407814]00406102 E8E5D7FFFF       call @ReadLn00406107 E854CCFFFF       call @_IOTest

Frankly, the best you can do is very similar to what you already have. The problem with what you already have is the heap allocation. Write your enumerator using a record rather than a class, like this:

type
TArrayEnumerator<T> = record
strict private
type
P = ^T;
strict private
FArr: P;
FIndex: Integer;
FCount: Integer;
public
class function Initialize(const Arr: array of T): TArrayEnumerator<T>; static;
function GetCurrent: T;
function MoveNext: Boolean;
property Current: T read GetCurrent;
end;

class function TArrayEnumerator<T>.Initialize(const Arr: array of T): TArrayEnumerator<T>;
begin
Result.FArr := @Arr[low(Arr)];
Result.FIndex := -1;
Result.FCount := Length(Arr);
end;

function TArrayEnumerator<T>.MoveNext: Boolean;
begin
Result := FIndex < FCount-1;
if Result then
inc(FIndex);
end;

function TArrayEnumerator<T>.GetCurrent: T;
var
Ptr: P;
begin
Ptr := FArr;
inc(Ptr, FIndex);
Result := Ptr^;
end;

然后你的 GetEnumerator 的实现如下:

function TMyClass.GetEnumerator: TArrayEnumerator<Integer>;
begin
Result := TArrayEnumerator<Integer>.Initialize(FItems);
end;

关于arrays - 如何在 Delphi 中公开私有(private)静态数组字段的内置枚举器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20846300/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com