【问题标题】:Typeinfo with record type does not work at runtime记录类型的类型信息在运行时不起作用
【发布时间】:2020-01-19 11:11:43
【问题描述】:

我在Delphi下编译有点问题:

function T_QS2ProcessMailbox.PutRec<T>(const aID: T_Barcode; var aRec: T;const aTxt: String): Boolean;
var
  FA: T_FahrauftragRec absolute aRec;
  LP: T_LagerpackungRec absolute aRec;
begin
  init_Rec;
  Rec.ID        := aID;
  Rec.EventTime := Now;
  Rec.Text      := aTxt;
  if TypeInfo(T_LagerpackungRec) = TypeInfo(T) then
  begin
    Rec.RecType := C_QS_TYPE_TLAGERPACKUNGREC;
    Rec.FA      := FA;
  end
  else
    if Typeinfo(T) = Typeinfo(T_LagerpackungRec) then
    begin
      Rec.RecType := C_QS_TYPE_TFAHRAUFTRAGREC;
      Rec.LP      := LP;
    end
    else
      Rec.RecType := C_QS_TYPE_TEXT;
  Send_TraceMsg(ClassName + '.PutRec Type=' + IntToStr(Rec.RecType));
  Result        := PutRec(Rec);
end;

它编译良好,没有错误、消息或提示。但它是在没有if 语句的情况下编译的。您可以在图片中查看它-此代码没有编译标记

我不明白为什么。

有人可以向我解释我做错了什么吗?

【问题讨论】:

    标签: delphi rtti typeinfo


    【解决方案1】:

    那些if 语句可以在编译时解析,因此对于任何给定的T 值,实际上只会编译其中的1 个。 (换句话说,编译后的代码永远不会为此函数执行任何if)。

    我可以想象仅看到 1 个编译标记的 2 个原因。要么您的应用程序将只使用 1 个 if 语句,要么 IDE 将所有 if 语句的编译标记映射到同一行(我发现最后一个不太可能,但我在IDE)。

    另一种可能性是您的第二个if 应该是

    if Typeinfo(T) = Typeinfo(T_FahrauftragRec) then
    

    而不是

    if Typeinfo(T) = Typeinfo(T_LagerpackungRec) then
    

    【讨论】:

      【解决方案2】:

      Typeinfo() 是 XE7 及更高版本中的编译器内在函数,因此可用于编译器在编译时评估1。而且由于T 的类型是编译器也知道的泛型,编译器可以直接评估您的ifs,并且任何评估为False 并且永远不会在运行时执行的块被简单地从最终可执行文件。这就是为什么您在它们上看不到任何调试器点的原因。

      1:但仅限于在通用方法内的if TypeInfo(T) = TypeInfo(X) 语句中使用TypeInfo(T) 的特定情况。 TypeInfo() 的其他用途在编译时没有类似的内联。

      这是正常行为,是您希望发生的事情,因为它会生成更精简、更高效的运行时代码。

      当您的其他代码调用 PutRec&lt;T_FahrauftragRec&gt;(...) 时,T 将是 T_FahrauftragRec,因此 TypeInfo(T_LagerpackungRec) = TypeInfo(T_FahrauftragRec) 将评估为 False。

      同样,当调用 PutRec&lt;T_LagerpackungRec&gt;(...) 时,T 将是 T_LagerpackungRec,因此 TypeInfo(T_FahrauftragRec) = TypeInfo(T_LagerpackungRec) 将评估为 False。

      对于传递给T 的任何其他类型,依此类推。

      另外,您的代码中存在错误。你的第二个if 声明:

      if Typeinfo(T) = Typeinfo(T_LagerpackungRec) then
      

      应该改为:

      if Typeinfo(T) = Typeinfo(T_FahrauftragRec) then
      

      【讨论】:

      • 对不起,但我的问题是关于其他事情:为什么编译器忽略了带有“if-statement”的 sn-p。我在其他代码中使用 PutRec() 进行了测试。
      • @svd71 "为什么编译器忽略了带有 'if-statement' 的 sn-p" - 我已经介绍过了。再仔细阅读我的答案。你接受了肯的回答,这基本上告诉你我做的同样的事情。编译器能够确定if 语句在运行时不会做任何事情,因此它会优化它们。在您的屏幕截图中,if 均未覆盖 T_FahrauftragRec,因此在调用 PutRec&lt;T_FahrauftragRec&gt;() 时,if 均被省略。
      猜你喜欢
      • 1970-01-01
      • 2021-11-11
      • 1970-01-01
      • 2010-11-27
      • 2011-11-09
      • 2015-03-21
      • 1970-01-01
      • 1970-01-01
      • 2016-08-30
      相关资源
      最近更新 更多