I\'m trying to convert my current Delphi 7 Win32 code to Delphi XE5 Android with minimal changes, so that my project can be cross-compiled to Win32 from a range of Delphi versio
This is rather a sum up of the two answers:
As pointed out by Remy Lebeau, ZEROBASEDSTRINGS
is a per-block conditional. That means that the following code will not work as expected:
const
s: string = 'test';
function StringLow(const aString: string): Integer; inline; // <-- inline does not help
begin
{$IF CompilerVersion >= 24}
Result := Low(aString); // Delphi XE3 and up can use Low(s)
{$ELSE}
Result := 1; // Delphi XE2 and below can't use Low(s), but don't have ZEROBASEDSTRINGS either
{$ENDIF}
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
{$ZEROBASEDSTRINGS OFF}
Memo1.Lines.Add(Low(s).ToString); // 1
Memo1.Lines.Add(StringLow(s).ToString); // 1
{$ZEROBASEDSTRINGS ON}
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
{$ZEROBASEDSTRINGS ON}
Memo1.Lines.Add(Low(s).ToString); // 0
Memo1.Lines.Add(StringLow(s).ToString); // 1 <-- Expected to be 0
{$ZEROBASEDSTRINGS OFF}
end;
There are 2 possible solutions:
A. Every time there's string items access or iteration place an IFDEF
around it, which is indeed a lot of clutter for the code, but will work properly irregardless of ZEROBASEDSTRINGS
setting around it:
for I := {$IFDEF XE3UP}Low(aText){$ELSE}1{$ENDIF} to {$IFDEF XE3UP}High(aText){$ELSE}Length(aText){$ENDIF} do
B. Since the ZEROBASEDSTRINGS
conditional is per-block
it never gets spoiled by 3rd party code and if you don't change it in your code you are fine (above StringLow
will work fine as long as the caller code has the same ZEROBASEDSTRINGS
setting). Note that if target is mobile, you should not apply ZEROBASEDSTRINGS OFF
globally in your code since RTL functions (e.g. TStringHelper
) will return 0-based results because mobile RTL is compiled with ZEROBASEDSTRINGS ON
.
On a side note - One might suggest to write an overloaded versions of Low/High
for older versions of Delphi, but then Low(other type)
(where type is array of something) stops working. It looks like since Low/High
are not usual functions then can not be overloaded that simply.
TL;DR - Use custom StringLow
and don't change ZEROBASEDSTRINGS
in your code.