Boy I wish that QC was still up and QualityPortal was publicly indexable as that would have saved me quite a bit of time tracking this down. Luckily I got help from Stefan Glienke (who maintains the awesome Spring4D library based on modern Delphi compiler support) when I mentioned
How good are you with reference to function?
I’ve an odd compiler thing throwing errors when using interfaces but not with classes.
So, for posterity:
Unlike C#, in Delphi interface methods are not compatible with method references or methods of object.
This has many manifestations, which means you can get a variety of compiler errors. I’ve listed the ones I could find below, but presume there are more and if I find more will update this post.
These are the errors you can get:
E2010 Incompatible types: ‘T’ and ‘Procedure’
E2035 Not enough actual parameters
E2250 There is no overloaded version of ‘FirstOrDefault’ that can be called with these arguments
These are the (now defunct, but used to be publicly accessible) QC and QualityPortal (needs sign on) entries (thanks Stefan Glienke and Blaise Thorn for reporting these):
The first public showing of that demo did not include main thread protection. It originates from a session at the the 1995 Borland Developers Conference where Ray Konopka showed the below code from Bob Ainsbury.
The latest version of Delphi, Delphi 2009, has a CurrentThread class property on the TThread class.
This will return the proper Delphi thread object if it’s a native thread. If the thread is an “alien” thread, i.e. created using some other mechanism or on a callback from a third party thread, then it will create a wrapper thread around the thread handle.
Last year, it took a while to reproduce and it is likely not fixed anytime soon: if you use Delphi and IBX (InterBase Express) to connect to either InterBase or FireBird database, then in the Turkish locale do not use lowercase SQL in your Delphi code as it will break on the
I’ve decided to put this in a separate post than the one I discovered the issue in as that one focused on the Unicode and language background of the various i/I/ characters and this post on the Delphi part.
uppercase / lowercase mappings (though this only impacts 2 characters — dotted and dotless “i”/”I” — and for only 2 cultures — Azeri and Turkish)
…
In general, this problem is called [WayBack] Case Folding and many environments do not have good and ready to use solutions for this.
Basically when working with case-insensitive language identifiers, you should always use culture invariant text comparison operations. In most languages, people use either lowercase or uppercase converted operations which for Delphi >= come down to using :
function LowerCase(string, TLocaleOptions.loInvariantLocale) instead of AnsiLowerCase(string) or LowerCase(string) without a TLocaleOptions enum value (which in retrospect should have been called TLocaleOption as it’s not a set type)
function UpperCase(string, TLocaleOptions.loInvariantLocale) instead of AnsiUpperCase(string) or UpperCase(string) without a TLocaleOptions enum value
without any parameter, LowerCase and UpperCase will implicitly behave as if called with TLocaleOptions.loInvariantLocale, but lots of people forget they do.
The functions ToLowerInvariant and ToUpperInvariant were added in Delphi XE3, but ToLower(LocaleID) and ToUpper(LocaleID) in Delphi XE4.
For IBX, I did the replacements in the diff below to fix it in Delphi XE8. I only replaced where identifiers were compared, not were actual database content was compared.
Unluckily, in the past IBX sources were hosted on CodeCentral at http://cc.embarcadero.com/Author/102 but no new bundles have been released since 2012.
Of all the locations I think IBX should not have used any case conversion here:
IBX.IBDatabaseINI.pas – function LocalServerPath(sFile: string): string
This function uses LowerCase() but I think an NTFS specific comparison should have been used, but I’ve not investigated into a solution for that yet.
Even when the Delphi team was large, the documentation was lacking, so with the reduced Delphi team size, I don’t have high expectations of the below to get fixed.
But since much of the post Delphi 7 run-time library looks a lot like the .NET core, you can usually fallback to the Microsoft documentation.
I knew that methods on interfaces were not compatible with the procedure of object (like [WayBack] TProc)or function of object construct, but they are also not compatible with the reference to procedure or reference to function construct.
It’s not nearly as good as the one by Uwe Raabe, but I didn’t really update this code for about a decade as it has functioned well for me in the current state: in 2009 it was like [WayBack] bo library – Source Code.
A couple of years ago I wrote a two-part article about a dataset enumerator: A Magical Gathering – Part 1 and Part 2. Well, things evolved a bit since then and I wondered how one would implement something similar given the current features of Delphi. Actually I am following here a suggestion from commenter Alan Clark.
So for now it’s just to document that my enumerator is there and that it works as intended.