前几天在盒子的帖子上讨论Delphi11的特性,一个朋友说希望有for in 0..100这种类似kotlin的循环语法。
随便指出了可以变相实现for in [0..100]即可,结果有其他朋友验证了,这种写法在DelphiXE1之前的版本是可以的,在高版本Delphi上实际上被认为是集合,那么就不能超过255个元素,无法实用。
好在高版本的Delphi的For in是通过数据类型有一个GetEnumerator方法返回枚举器来实现的,一些简单数组之类的靠编译器自动处理的。
那么就可以变相实现这个功能了。
type
//这是一个辅助类
TForInHelper = record
strict private
type
TEnumerator = class
private
FLowValue, FHighValue : Integer;
FIndex: NativeInt;
function GetCurrent: Integer;
public
constructor Create(ALowValue, AHighValue : Integer);
function MoveNext: Boolean;
procedure Reset;
property Current: Integer read GetCurrent;
end;
var
FLowValue, FHighValue : Integer;
public
function GetEnumerator(): TEnumerator;
class function Create(l, h : Integer):TForInHelper;static;
end;
{ TForInHelper.TEnumerator }
constructor TForInHelper.TEnumerator.Create(ALowValue, AHighValue: Integer);
begin
FLowValue := ALowValue;
FHighValue := AHighValue;
FIndex := FLowValue - 1; //先MoveNext,然后才GetCurrent,所以要先把Index比Low值小一个
end;
function TForInHelper.TEnumerator.GetCurrent: Integer;
begin
Result := FIndex;
end;
function TForInHelper.TEnumerator.MoveNext: Boolean;
begin
Result := False;
if FIndex >= FHighValue then
Exit;
Inc(FIndex);
Result := True;
end;
procedure TForInHelper.TEnumerator.Reset;
begin
FIndex := FLowValue;
end;
{ TForInHelper }
class function TForInHelper.Create(l, h: Integer): TForInHelper;
begin
Result.FLowValue := l;
Result.FHighValue := h;
end;
function TForInHelper.GetEnumerator: TEnumerator;
begin
Result := TEnumerator.Create(FLowValue, FHighValue);
end;
//ForInHelper
function FH(l, h : Integer): TForInHelper;
begin
Result := TForInHelper.Create(l, h);
end;
for var i in FH(0,100) do
begin
OutputDebugString(PChar(format('%d',[i])));
end;
这就变相的实现了仿kotlin这种直接for in循环。写起来比原来的for var i := 0 to 100 do 好读一点,代码似乎简介一点。
只是这个辅助类没法完全覆盖真正的子界类型,因为只支持Integer数据类型,而不思全部有序类型。
经过写这个辅助类,我也很希望官方编译器能支持for in 0..100 do这样的语法,又好写又好读。