procedure ExtractHeaderFields(Separators,_WhiteSpace: TSysCharSet; Content: PChar; Strings: TStrings; Decode: Boolean; StripQuotes: Boolean = False); {$ENDIF NEXTGEN} var Head,Tail: PChar; EOS,InQuote,LeadQuote: Boolean; QuoteChar: Char; ExtractedField: string; {$IFNDEF NEXTGEN} WhiteSpaceWithCRLF: TSysCharSet; SeparatorsWithCRLF: TSysCharSet; {$ENDIF !NEXTGEN} function DoStripQuotes(const S: string): string; var I: Integer; InStripQuote: Boolean; StripQuoteChar: Char; begin Result := S; InStripQuote := False; StripQuoteChar := #0; if StripQuotes then begin for I := Result.Length - 1 downto 0 do if Result.Chars[I].IsInArray(['''','"']) then if InStripQuote and (StripQuoteChar = Result.Chars[I]) then begin Result.Remove(I,1); InStripQuote := False; end else if not InStripQuote then begin StripQuoteChar := Result.Chars[I]; InStripQuote := True; Result.Remove(I,1); end end; end;
当我使用TPageProducer时,我看到这个被调用,我可以看到我的好源代码字符串进入上面的ExtractHeaderFields例程,然后进入’DoStripQuotes’函数.进入DoStripQuotes并观察’Result’表明它不会改变,即使调用Result.Remove(剥离引号)也是如此.当我将这个’DoStripQuotes’例程带到一个简单的测试应用程序时,它不会编译,告诉我’Result.anything’是不允许的.我假设那个结果,虽然它被定义为’string’,但必须是Web.HTTPProd上下文中的另一种类型的字符串.
所以我想到这可能与我听说过的“不变的字符串”有关.我读到了这个SO question,虽然我得到了要点,但我可以提供更实用的建议.
具体来说,我想回答以下问题:
>如果允许使用符号Result.Length,那么’string’是什么类型的’结果’?
>有没有一种方法可以告诉编译器为单元使用’XE3’兼容性? (这可能让我看到问题的起源).我试过{$ZEROBASEDSTRINGS ON} / OFF但这似乎导致更多的混乱,我不知道我在做什么!
谢谢你的帮助.
稍后编辑:如下面接受的答案中所述,这是VCL单元Web.HTTPApp.pas中的一个错误,它应该在2645行的两个地方读取“Result:= Result.Remove(I,1)”而不是“结果”.删除(1,1)”
解决方法
What type of ‘string’ is ‘Result’ if the notation Result.Length is allowed?
它只是与UnicodeString相同的旧字符串,自Delphi 2009以来一直在使用.不同之处在于此代码使用新的记录助手(特别是SysUtils.TStringHelper).这就是让你使用的东西.字符串变量的表示法.
Is there a way in which I can tell the compiler to use ‘XE3’ compatibility for a unit?
不.有问题的代码是库单元,它设计为以特定模式编译.更重要的是,除非你自己编译RTL / VCL,否则你不能轻易地重新编译它.即使有这样的模式,也没有用,因为代码完全错误(见下文).没有多少模式切换可以修复这段特定的代码.
I get to thinking maybe this is something to do with the Immutable strings that I’ve heard about.
不是. Delphi编译器都没有不可变的字符串.不可变字符串的概念只是作为未来变化浮现的东西.如果进行了更改,则希望首先在移动编译器中进行更改.
问题实际上只是你发布的代码中一个相当简单的错误,它根本没有任何测试.删除的使用是错误的.该方法不会就地修改字符串.相反,它返回一个删除了字符的新字符串.代码应为:
Result := Result.Remove(I,1);
编写ExtractHeaderFields的开发人员犯了这个错误的原因是谁设计了错误地命名为Remove方法的字符串帮助程序代码.由于Remove是一个动词,你可以期望它就地操作.如此方法不会修改主题并返回新实例的方法应该被赋予名词.所以这个方法应该被命名为Remnants.在我看来,好像RTL设计师复制了同样存在缺陷的.net命名.
如果QC报告尚不存在,您应该提交.我知道XE4 update 1刚刚发布.它包含修复它似乎是合理的.
正如我所看到的,您的其他选择是:
>坚持使用XE3,直到XE4充分调试.>在项目中包含Web.HTTPApp单元的副本并自行修复错误.