<div dir="auto"><div><div class="gmail_quote"><div dir="ltr" class="gmail_attr">Michael Van Canneyt <<a href="mailto:michael@freepascal.org">michael@freepascal.org</a>> schrieb am Di., 10. März 2020, 08:11:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><br>
<br>
On Tue, 10 Mar 2020, Anthony Walter via fpc-pascal wrote:<br>
<br>
> I started adding {$modeswitch multihelpers} to some of my code and noticed<br>
> a problem. It would seem that the SysUtils unit is defining type helpers<br>
> for the string type and this led me to discover that multiple type helpers<br>
> takes precedence over other helpers in a way that is conflicts with other<br>
> pascal rules.<br>
><br>
> To demonstrate, if I have MyUnit.pas that defines a string type helper<br>
> with EndsWith() and an IntToStr() function then consider the following code:<br>
><br>
> program Test;<br>
><br>
> uses<br>
>  MyUnit, SysUtils;<br>
><br>
> begin<br>
>  'hello'.EndsWith('lo'); // invokes MyUnit.TStringHelper.EndsWith()<br>
>  IntToStr(12); // invokes SysUtils.IntToStr()<br>
> end.<br>
><br>
> But if I reverse the uses order:<br>
><br>
> program Test;<br>
><br>
> uses<br>
>  SysUtils, MyUnit;<br>
><br>
> begin<br>
>  'hello'.EndsWith('lo'); // invokes SysUtils.TStringHelper.EndsWith()<br>
>  IntToStr(12); // invokes MyUnit.IntToStr()<br>
> end.<br>
><br>
> What should happen is that both examples use the function from the last<br>
> unit in the uses clause. Using the example above with "uses SysUtils,<br>
> MyUnit;" the following should happen:<br>
><br>
>  'hello'.EndsWith('lo'); // invokes MyUnit.TStringHelper.EndsWith()<br>
>  IntToStr(12); // invokes MyUnit.IntToStr()<br>
><br>
> I know some of you might see this as a small problem, but it's an<br>
> inconstancy that can lead to a situation where the wrong methods will be<br>
> called without being obvious. The standard has long been that when an<br>
> identifier of the same name is is found, pascal will choose to identify the<br>
> name as the one coming from the last matching unit in the uses clause.<br>
> Multiple type helpers should follow this same rule.<br>
<br>
I'm inclined to think you found the reason why Embarcadero disallows type<br>
helpers.<br>
<br>
A type helper extends a type with some additional methods. Since the<br>
sysutils unit comes first in the uses clause, it is the first to extend the<br>
string type. Then comes the myunit helper, which tries to extend the same<br>
type with the same methods. The compiler sees the first attached method.<br>
<br>
I agree the order of the units is relevant, but I think that it is acting<br>
more like unit initialization & class constructor order <br>
(if viewed as 'attaching methods to type') than like identifier scope <br>
(if viewed as 'looking for method identifier').<br>
<br>
So while I agree it may be confusing, it's not necessarily wrong.<br>
<br>
I suppose Sven can shed some light on the matter.<br></blockquote></div></div><div dir="auto"><br></div><div dir="auto">It should work as with normal identifiers and multiple helpers without the modeswitch (there the last one wins as well). So this is indeed a bug (though hopefully easy to solve). </div><div dir="auto"><br></div><div dir="auto">@Anthony: would you report that, please? </div><div dir="auto"><br></div><div dir="auto">Regards, </div><div dir="auto">Sven </div><div dir="auto"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
</blockquote></div></div></div>