我尝试将一些代码从D2007移植到DXE2。 这个简化的代码在D2007中编译得很好。在DXE2中显示此错误:
[DCC Warning] Unit1.pas(10): W1050 WideChar reduced to byte char in set expressions. Consider using 'CharInSet' function in 'SysUtils' unit.
[DCC Error] Unit1.pas(37): E2010 Incompatible types: 'AnsiChar' and 'Char'
可能是unicode问题。 有人能告诉我为什么会发生这种情况以及我该如何纠正它?
此致
代码:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;
type
TSetOfChar = Set of Char; // Line 10
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
private
FCharacterSet: TSetOfChar;
public
property CharacterSet: TSetOfChar read FCharacterSet write FCharacterSet;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
var
CharacterSet: TSetOfChar;
j: Integer;
s: String;
begin
CharacterSet := [];
s := 'I''m just testing åäö';
for j := 1 to Length(s) do
Include(CharacterSet, s[j]); // <- Line 37
end;
end.
编辑:请注意,我使用的是没有泛型的Delphi 2007。我想要在D2007中仍然有效的代码,因为有很多代码要移植到Unicode。这是一个缓慢的过程。 当一切都被移植,验证它适用于XE2然后我们可以使用XE2之类的东西。与此同时,我们像往常一样维护D2007,我们希望避免在修订控制系统中建立XE2分支。
答案 0 :(得分:8)
这是标准的Unicode Delphi迁移饲料。需要阅读的是MarcoCantù的论文 White Paper: Delphi and Unicode。如果您还没有读过,请这样做。如果您最近没有阅读过,请再次阅读。
set of char
产生警告的原因是集合的基本类型不能超过256个值。但由于char
现在是UTF-16,所以这远远超过256.这意味着你的代码永远不能使用集合和UTF-16字符。
您可以使用set of AnsiChar
和AnsiString
。但是,如果您希望此代码处理Unicode数据,那么您将需要使用set
之外的其他内容。例如,可以使用TList<char>
。
var
CharacterSet: TList<char>;
s: string;
c: char;
.....
CharacterSet := TList<char>.Create;
s := 'I''m just testing åäö';
for c in s do
if not CharacterSet.Contains(c) then
CharacterSet.Add(c);
我不建议用于制作。它的性能特征会很糟糕。基于哈希的字典会做得更好。最重要的是一个专门的大型课程。
最后一点。字符与UTF-16中的代码点不同,后者是可变长度编码。有问题的代码和这个答案不予考虑。