Delphi 如何区分旧式的object和record? 程序项目15; {$APPTYPE控制台} {$R*.res} 使用 System.Rtti、System.TypInfo; 类型 记录 公众的 AField:整数; 构造函数初始化(测试:整数); 结束; TOldObject=对象 公众的 AField:整数; 构造函数初始化(测试:整数); 程序幻想;虚拟的

Delphi 如何区分旧式的object和record? 程序项目15; {$APPTYPE控制台} {$R*.res} 使用 System.Rtti、System.TypInfo; 类型 记录 公众的 AField:整数; 构造函数初始化(测试:整数); 结束; TOldObject=对象 公众的 AField:整数; 构造函数初始化(测试:整数); 程序幻想;虚拟的,delphi,delphi-xe2,rtti,Delphi,Delphi Xe2,Rtti,旧对象已弃用 因此,您不应该将其与新的rtti结合使用 反对的第一步是禁止虚拟方法。我想是因为编译器的回归 这是Embarcadero模仿C#及其结构/类范式的决定。错误的决策imho。据我所知,在Delphi的RTTI框架中,旧式对象无法与记录区分开来。这个节目 program Project15; {$APPTYPE CONSOLE} {$R *.res} uses System.Rtti, System.TypInfo; type TRecord = record pub

旧对象已弃用

因此,您不应该将其与新的rtti结合使用

反对的第一步是禁止虚拟方法。我想是因为编译器的回归


这是Embarcadero模仿C#及其结构/类范式的决定。错误的决策imho。

据我所知,在Delphi的RTTI框架中,旧式对象无法与记录区分开来。这个节目

program Project15;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  System.Rtti, System.TypInfo;

type
  TRecord = record
  public
    AField: integer;
    constructor Init(test: integer);
  end;

  TOldObject = object
  public
    AField: integer;
    constructor Init(test: integer);
    procedure Fancy; virtual;    <<--- compiles
    class operator Implicit(test: TRecord): TOldObject; <<-- does not compile.
  end;

procedure IsObjectARecord;
var
  ARecord: TRecord;
  AObject: TOldObject;
  v: TValue;
  s: String;
begin
  v:= TValue.From(ARecord);
  case v.Kind of
    tkRecord: WriteLn('it''s a Record');
  end;
  ARecord:= TRecord.Init(10);
  AObject.Init(10);
  v:= TValue.From(AObject);
  case v.Kind of
    tkRecord: begin
      WriteLn('object is a record?');
      if v.IsObject then s:= 'true'
      else s:= 'false';
      WriteLn('isObject = ' + s);
      WriteLn('ToString says: '+v.ToString);
    end;
  end;

end;
{ TOldSkool }

constructor TOldObject.Init(test: integer);
begin
  AField:= 10;
end;

constructor TRecord.Init(test: integer);
begin
  AField:= 10;
end;

begin
  IsObjectARecord;
  Readln;
end.
输出

{$APPTYPE CONSOLE}

uses
  System.Rtti;

type
  TOldObject = object
  end;

var
  ctx: TRttiContext;
  RttiType: TRttiType;
begin
  RttiType := ctx.GetType(TypeInfo(TOldObject));
  Writeln(TValue.From(RttiType.TypeKind).ToString);
  Writeln(RttiType.IsRecord);
  Readln;
end.
tkRecord 真的
对象的实例可以存在于堆栈或堆上。与records.FWIW一样,如果将冒号转换为分号,虚拟方法将编译。注意,您的语法错误不会编译,但虚拟方法会编译(在XE4中测试)。运算符未按预期编译。谢谢Rudy;吸取的教训;当咖啡因含量低时不要编码@Arnaud这并没有回答所问的问题。你应该把它变成一个注释。这确实应该是一个注释,虚拟方法是不允许的。该行中有一个语法错误,这就是它无法编译的原因。所以不要告诉我它仍然可用。IMHO我回答了关于rtti的问题:对象不再被使用,所以新的rtti不支持它,旧的rtti也不支持它,因为它已经专注于类。@Johan,因为你应该在2014年使用
object
,如果你想扩展并发编程,就像你对像Rust这样的现代语言所做的那样,请看@ArnaudBouchez,你回答了一个不同的问题。您回答:“我应该使用对象吗?” tkRecord TRUE