通用整数的奇怪 PTypeInfo 名称
Strange PTypeInfo name for generic integer
我需要对通用类型和 return 作为字符串进行 "smart" 检测,但目前我不明白为什么 delphi 会添加一些奇怪的标识PTypeInfo.Name 属性.
我目前的情况是:
program SO_29674887;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
System.TypInfo;
type
TypeResolver = class
strict private
class function ReCast<T>(const AValue) : T;
public
class function Format<T>(const AValue : T) : string;
end;
Compare = class
public
class function IsEqual<A;B>(const AVal : A; BVal : B) : string;
end;
{ TypeResolver }
class function TypeResolver.ReCast<T>(const AValue): T;
begin
Result := T(AValue);
end;
class function TypeResolver.Format<T>(const AValue: T): string;
var Info : PTypeInfo;
begin
Info := TypeInfo(T);
Result := 'undefined';
if(Info.Kind = tkInteger) then
begin
if(Info.Name = GetTypeName(TypeInfo(Byte))) then
Result := IntToStr(ReCast<Byte>(AValue))
else if(Info.Name = GetTypeName(TypeInfo(ShortInt))) then
Result := IntToStr(ReCast<ShortInt>(AValue))
else if(Info.Name = GetTypeName(TypeInfo(SmallInt))) then
Result := IntToStr(ReCast<SmallInt>(AValue))
else if(Info.Name = GetTypeName(TypeInfo(Integer))) then
Result := IntToStr(ReCast<Integer>(AValue));
end;
Result := Info.Name + ':' + Result;
end;
{ Compare }
class function Compare.IsEqual<A, B>(const AVal: A; BVal: B): string;
begin
Result := Format('%s = %s', [
TypeResolver.Format<A>(AVal),
TypeResolver.Format<B>(BVal)]);
end;
var PAUSE : string;
begin
try
{ TODO -oUser -cConsole Main : Insert code here }
WriteLn(Compare.IsEqual(0, 255));
WriteLn(Compare.IsEqual(-127, 127));
WriteLn(Compare.IsEqual(0, 65535));
WriteLn(Compare.IsEqual(-32768, 32767));
WriteLn(Compare.IsEqual(0, 4294967295));
WriteLn(Compare.IsEqual(-2147483648, 2147483647));
Readln(PAUSE);
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
这里发生的是 delphi 没有给我整数的实际类型名称,而是给我奇怪的标识符,如 :2、:4、:6 等
例如:
Compare.IsEqual(0, 255); //Gives Info.Name = :2, Byte
Compare.IsEqual(-127, 127); //Gives Info.Name = ShortInt, :4
Compare.IsEqual(0, 65535); //Gives Info.Name = :6, Word
Compare.IsEqual(-32768, 32767); //Gives Info.Name = SmallInt, :8
Compare.IsEqual(0, 4294967295); //Gives Info.Name = :01, Cardinal
Compare.IsEqual(-2147483648, 2147483647); //Gives Info.Name = Integer, :21
所以我的问题是,如果在我看来 delphi 在传递这些标识符时没有提供任何实际类型的线索,以及它为什么给出这些标识符,我该如何找到正确的类型进行转换奇数标识符。
在我看来,您似乎在尝试发明位于 RTTI.pas
中的 TValue
我已经使用 TValue 重写了您的示例。
在表单和以下代码中放置一个 TMemo:
uses
RTTI;
type
TypeResolver = class
public
class function ReCast<T>(const AValue): T;
class function Format<T>(const AValue: T): string;
end;
Compare = class
public
class function IsEqual<A; B>(const AValA: A; const AValB: B): string;
end;
class function Compare.IsEqual<A, B>(const AValA: A; const AValB: B): string;
begin
Result := Format('%s = %s', [TypeResolver.Format<A>(AValA), TypeResolver.Format<B>(AValB)]);
end;
{ TypeResolver }
class function TypeResolver.ReCast<T>(const AValue): T;
begin
Result := T(AValue);
end;
class function TypeResolver.Format<T>(const AValue: T): string;
begin
Result := TValue.From(AValue).TypeInfo.Name;
end;
procedure TForm13.FormCreate(Sender: TObject);
begin
Memo1.Lines.Add(Compare.IsEqual(0, 255));
Memo1.Lines.Add(Compare.IsEqual(-127, 127));
Memo1.Lines.Add(Compare.IsEqual(0, 65535));
Memo1.Lines.Add(Compare.IsEqual(-32768, 32767));
Memo1.Lines.Add(Compare.IsEqual(0, 4294967295));
Memo1.Lines.Add(Compare.IsEqual(-2147483648, 2147483647));
Memo1.Lines.Add(Compare.IsEqual(Form13, Memo1));
end;
我相信它对你来说很厚?
这是上面的输出:
ShortInt = Byte
ShortInt = ShortInt
ShortInt = Word
SmallInt = SmallInt
ShortInt = Cardinal
Integer = Integer
TForm13 = TMemo
这是我的复制品,稍微短一些。
{$APPTYPE CONSOLE}
uses
System.TypInfo;
type
TypeResolver = class
public
class function Format<T>(const AValue : T) : string;
end;
class function TypeResolver.Format<T>(const AValue: T): string;
var
Info: PTypeInfo;
begin
Info := TypeInfo(T);
Result := Info.Name;
end;
begin
Writeln(TypeResolver.Format(0));
Writeln(TypeResolver.Format<Byte>(0));
Writeln(TypeResolver.Format(255));
Readln;
end.
在 XE2 中输出是:
:3
Byte
Byte
在 XE6 及更高版本中,输出为:
ShortInt
Byte
Byte
从 0
的文字推断时,Delphi 的早期版本似乎创建了一个名称难以形容的私有类型。我不能说为什么会这样。由于行为发生了变化,因此只能假设 Embarcadero 工程师进行了更改以修复他们认为的缺陷。
换句话说,您所观察到的行为似乎是一个错误。
我创建私有类型的假设得到了这个程序的支持:
{$APPTYPE CONSOLE}
uses
System.SysUtils,
System.TypInfo;
type
TypeResolver = class
public
class function Format<T>(const AValue : T) : string;
end;
class function TypeResolver.Format<T>(const AValue: T): string;
var
Info: PTypeInfo;
TypeData: PTypeData;
begin
Info := TypeInfo(T);
Result := Info.Name;
if Info.Kind=tkInteger then begin
TypeData := GetTypeData(Info);
Result := Result + ', min = ' + IntToStr(TypeData.MinValue) +
', max = ' + IntToStr(TypeData.MaxValue);
end;
end;
begin
Writeln(TypeResolver.Format(0));
Readln;
end.
在 XE2 上输出是:
:3, min = 0, max = 127
在 XE6 上输出是:
ShortInt, min = -128, max = 127
所以我认为这是泛型类型推断的问题,我们可以将其归因于 XE6 中修复的错误。
对于您应该如何解决这个问题,我没有任何建议,因为我不知道您的实际问题。也就是说,通常最好尽可能避免比较类型名称。
我需要对通用类型和 return 作为字符串进行 "smart" 检测,但目前我不明白为什么 delphi 会添加一些奇怪的标识PTypeInfo.Name 属性.
我目前的情况是:
program SO_29674887;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
System.TypInfo;
type
TypeResolver = class
strict private
class function ReCast<T>(const AValue) : T;
public
class function Format<T>(const AValue : T) : string;
end;
Compare = class
public
class function IsEqual<A;B>(const AVal : A; BVal : B) : string;
end;
{ TypeResolver }
class function TypeResolver.ReCast<T>(const AValue): T;
begin
Result := T(AValue);
end;
class function TypeResolver.Format<T>(const AValue: T): string;
var Info : PTypeInfo;
begin
Info := TypeInfo(T);
Result := 'undefined';
if(Info.Kind = tkInteger) then
begin
if(Info.Name = GetTypeName(TypeInfo(Byte))) then
Result := IntToStr(ReCast<Byte>(AValue))
else if(Info.Name = GetTypeName(TypeInfo(ShortInt))) then
Result := IntToStr(ReCast<ShortInt>(AValue))
else if(Info.Name = GetTypeName(TypeInfo(SmallInt))) then
Result := IntToStr(ReCast<SmallInt>(AValue))
else if(Info.Name = GetTypeName(TypeInfo(Integer))) then
Result := IntToStr(ReCast<Integer>(AValue));
end;
Result := Info.Name + ':' + Result;
end;
{ Compare }
class function Compare.IsEqual<A, B>(const AVal: A; BVal: B): string;
begin
Result := Format('%s = %s', [
TypeResolver.Format<A>(AVal),
TypeResolver.Format<B>(BVal)]);
end;
var PAUSE : string;
begin
try
{ TODO -oUser -cConsole Main : Insert code here }
WriteLn(Compare.IsEqual(0, 255));
WriteLn(Compare.IsEqual(-127, 127));
WriteLn(Compare.IsEqual(0, 65535));
WriteLn(Compare.IsEqual(-32768, 32767));
WriteLn(Compare.IsEqual(0, 4294967295));
WriteLn(Compare.IsEqual(-2147483648, 2147483647));
Readln(PAUSE);
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
这里发生的是 delphi 没有给我整数的实际类型名称,而是给我奇怪的标识符,如 :2、:4、:6 等
例如:
Compare.IsEqual(0, 255); //Gives Info.Name = :2, Byte
Compare.IsEqual(-127, 127); //Gives Info.Name = ShortInt, :4
Compare.IsEqual(0, 65535); //Gives Info.Name = :6, Word
Compare.IsEqual(-32768, 32767); //Gives Info.Name = SmallInt, :8
Compare.IsEqual(0, 4294967295); //Gives Info.Name = :01, Cardinal
Compare.IsEqual(-2147483648, 2147483647); //Gives Info.Name = Integer, :21
所以我的问题是,如果在我看来 delphi 在传递这些标识符时没有提供任何实际类型的线索,以及它为什么给出这些标识符,我该如何找到正确的类型进行转换奇数标识符。
在我看来,您似乎在尝试发明位于 RTTI.pas
中的 TValue我已经使用 TValue 重写了您的示例。
在表单和以下代码中放置一个 TMemo:
uses
RTTI;
type
TypeResolver = class
public
class function ReCast<T>(const AValue): T;
class function Format<T>(const AValue: T): string;
end;
Compare = class
public
class function IsEqual<A; B>(const AValA: A; const AValB: B): string;
end;
class function Compare.IsEqual<A, B>(const AValA: A; const AValB: B): string;
begin
Result := Format('%s = %s', [TypeResolver.Format<A>(AValA), TypeResolver.Format<B>(AValB)]);
end;
{ TypeResolver }
class function TypeResolver.ReCast<T>(const AValue): T;
begin
Result := T(AValue);
end;
class function TypeResolver.Format<T>(const AValue: T): string;
begin
Result := TValue.From(AValue).TypeInfo.Name;
end;
procedure TForm13.FormCreate(Sender: TObject);
begin
Memo1.Lines.Add(Compare.IsEqual(0, 255));
Memo1.Lines.Add(Compare.IsEqual(-127, 127));
Memo1.Lines.Add(Compare.IsEqual(0, 65535));
Memo1.Lines.Add(Compare.IsEqual(-32768, 32767));
Memo1.Lines.Add(Compare.IsEqual(0, 4294967295));
Memo1.Lines.Add(Compare.IsEqual(-2147483648, 2147483647));
Memo1.Lines.Add(Compare.IsEqual(Form13, Memo1));
end;
我相信它对你来说很厚?
这是上面的输出:
ShortInt = Byte
ShortInt = ShortInt
ShortInt = Word
SmallInt = SmallInt
ShortInt = Cardinal
Integer = Integer
TForm13 = TMemo
这是我的复制品,稍微短一些。
{$APPTYPE CONSOLE}
uses
System.TypInfo;
type
TypeResolver = class
public
class function Format<T>(const AValue : T) : string;
end;
class function TypeResolver.Format<T>(const AValue: T): string;
var
Info: PTypeInfo;
begin
Info := TypeInfo(T);
Result := Info.Name;
end;
begin
Writeln(TypeResolver.Format(0));
Writeln(TypeResolver.Format<Byte>(0));
Writeln(TypeResolver.Format(255));
Readln;
end.
在 XE2 中输出是:
:3 Byte Byte
在 XE6 及更高版本中,输出为:
ShortInt Byte Byte
从 0
的文字推断时,Delphi 的早期版本似乎创建了一个名称难以形容的私有类型。我不能说为什么会这样。由于行为发生了变化,因此只能假设 Embarcadero 工程师进行了更改以修复他们认为的缺陷。
换句话说,您所观察到的行为似乎是一个错误。
我创建私有类型的假设得到了这个程序的支持:
{$APPTYPE CONSOLE}
uses
System.SysUtils,
System.TypInfo;
type
TypeResolver = class
public
class function Format<T>(const AValue : T) : string;
end;
class function TypeResolver.Format<T>(const AValue: T): string;
var
Info: PTypeInfo;
TypeData: PTypeData;
begin
Info := TypeInfo(T);
Result := Info.Name;
if Info.Kind=tkInteger then begin
TypeData := GetTypeData(Info);
Result := Result + ', min = ' + IntToStr(TypeData.MinValue) +
', max = ' + IntToStr(TypeData.MaxValue);
end;
end;
begin
Writeln(TypeResolver.Format(0));
Readln;
end.
在 XE2 上输出是:
:3, min = 0, max = 127
在 XE6 上输出是:
ShortInt, min = -128, max = 127
所以我认为这是泛型类型推断的问题,我们可以将其归因于 XE6 中修复的错误。
对于您应该如何解决这个问题,我没有任何建议,因为我不知道您的实际问题。也就是说,通常最好尽可能避免比较类型名称。