So, I was working on yet another app, and stumbled onto yet another Delphi compiler/RTL issue.
Here's a sample reproducible test case:
program MercuryApp; // chuacw {$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils, System.Classes; var LLine: AnsiString; List: TStringList; Count: Integer; begin ReportMemoryLeaksOnShutdown := True; Count := 0; List := TStringList.Create; try List.Add('Hello world'); List.Add('Goodbye!'); for LLine in List do // Compiler warning Implicit string cast with potential data loss from 'string' to 'AnsiString' WriteLn(LLine); // String cast to eliminate warning for LLine in AnsiString(List) do // But goes into an infinite loop!!! begin WriteLn(LLine); Inc(Count); end; finally List.Free; end; end.
As you can see, I was trying to enumerate through the items in a TStringList, which is a container for strings.However, what I'm using to enumerate through the items, is an AnsiString, instead of a string.
So, trying to eliminate the warning, I casted the TStringList into an AnsiString, and that's when the trouble began!
How do you distinguish between casting TStringList into an AnsiString, and distingush casting the items returned by GetCurrent into an AnsiString?
The proper way to do it would be as follows, but is there an easier or undocumented way? The problem is that since there's no formal Delphi grammar listed on the Embarcadero docwiki site, it's challenging to discover what's the proper grammar to do so.
program MercuryApp; var LLine: AnsiString; ALine: string; List: TStringList; begin for ALine in List do begin LLine := AnsiString(ALine); // do whatever with LLine here end; ... end.
In 2017, with the release of Delphi 10.2 Tokyo, Embarcadero introduced a specialized implementation of the Observer pattern into the System.Classes unit. While it has been in the wild for 9 years, it remains a "hidden" architecture for many, primarily because it serves as the invisible engine behind LiveBindings. Other than live bindings, you can also use the Observer pattern as a way to update component settings to the Windows registry, an .ini file, or persist it elsewhere.
System.Classes