2

我有以下代码(简化):

program Project1;

{$APPTYPE CONSOLE}

uses
  SysUtils,
  Unit1 in 'Unit1.pas';

var
  f: TFoo<Integer>;
begin
  f := TFoo<Integer>.Create;
  f.Baz;
  Readln;
end.


unit Unit1;

{$D-}

interface

type
  TFoo = class
  public
    procedure Bar(const s: string);
  end;

  TFoo<T> = class(TFoo)
  public
    procedure Baz;
  end;

implementation

uses
  TypInfo;

{ TFoo }

procedure TFoo.Bar(const s: string);
begin
  Writeln(s);
end;

{ TFoo<T> }

procedure TFoo<T>.Baz;
begin
  Bar(PTypeInfo(TypeInfo(T)).Name);
end;

end.

f.Baz现在,当我进入时,Unit1.TFoo<T>.Baz虽然我明确禁用了该单元的调试信息,但我无法进入TFoo.Bar哪个是正确的。我认为这是因为泛型在内部是如何实现的(如模板),并且因为TFoo<Integer>在我的Project1. 当我添加以下单元时,我无法再进入Baz

unit Unit2;

{$D-}

interface

uses
  Unit1;

type
  TIntegerFoo = TFoo<Integer>;

implementation

end.

现在有什么方法可以完全删除泛型类型的调试信息,这样我就可以在任何地方(调试信息所在的位置)专门化该类型,但避免进入泛型类型的方法?Generics.Collections.TList<T>我想这一定是可能的,因为如果不启用“使用调试 .dcus”选项,我将无法执行任何方法。

4

1 回答 1

3

经过一些实验,似乎是否启用调试信息的确定由引用该类型的特定实例的第一个单元控制。

因此,如果编译器第一次遇到类型的实例化,启用调试信息,那么特定类型将使用调试信息进行编译。另一方面,如果第一次实例化是在没有调试信息的单元中,那么将没有调试信息。

在您的示例中,第一个(也是唯一一个)实例化TFoo<Integer>在 .dpr 文件中,该文件确实启用了调试信息。因此,如果您将 .dpr 文件移至{$D-}.dpr 文件中并设置{$D+}Unit1您会发现没有 .dpr 的调试信息TFoo<Integer>.Baz

我说第一次实例化的原因是可能有很多不同的单元实例化TFoo<Integer>。编译器遇到的第一个问题是确定实例化类型是否使用调试信息进行编译。

可以安排TFoo<Integer>有调试信息,但TFoo<string>没有调试信息。


我想这一定是可能的,因为如果不启用“使用调试 .dcus”选项,我将无法步进任何 Generics.Collections.TList 方法。

我无法解释。根据我的假设,调试信息应该可用于 TList 实例化,如果调试信息在您第一次实例化类时打开。

我怀疑调试器中可能存在错误。例如,我编写了以下程序:

{$APPTYPE CONSOLE}
uses
  Generics.Collections;
begin
  TList<Integer>.Create.Add(6);
end.

当我在关闭启用调试 DCU 的情况下运行它时,我确实可以进入Generics.Collections. 但是我完全走错了地方。它降落在TList<T>.Pack

所以,很抱歉我不能提供更多的见解,但是你问题的这个方面让我感到困惑。

于 2012-12-11T13:21:49.300 回答