【问题标题】:How to inspect the content of non-generic TObjectList when debugging?调试时如何检查非泛型 TObjectList 的内容?
【发布时间】:2011-03-14 05:52:13
【问题描述】:

总结:
1. 调试时手动类型转换,正如 LachlanG 和 Ken 指出的那样。
2. 利用 Delphi 2010 以来引入的 Debugger Visualizers 的概念。
3. 切换到泛型对应物。

==========================================

以如下代码为例:

如果断点分别设置在TestRegular的末尾和TestGenerics的末尾,则可以通过调试检查器看到通用列表的项目(甚至项目的内容),但是当一个人将鼠标悬停在tmp 变量上时,对于常规的 tobjectlist 来说没有任何意义(甚至不是计数)。我想知道是否有某种方法可以为常规 tobjectlist 实现类似的调试时功能?

    unit Unit2;

    interface

    uses
      Contnrs, Generics.Collections,
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs;

    type
      TMyItem = class;
      TMyItemList = class;
      TForm2 = class;

      TMyItem = class
      private
        fname: string;
      public
        property name: string read fname;
        constructor Create(aName: string);
      end;

      TMyItemList = class(TObjectList)
      protected
        procedure SetObject (Index: Integer; Item: TMyItem);
        function GetObject (Index: Integer): TMyItem;
      public
        function Add (Obj: TMyItem): Integer;
        procedure Insert (Index: Integer; Obj: TMyItem);
        property Objects [Index: Integer]: TMyItem
          read GetObject write SetObject; default;
      end;

      TForm2 = class(TForm)
        procedure FormCreate(Sender: TObject);
      private
        { Private declarations }
        procedure TestRegular;
        procedure TestGenerics;
      public
        { Public declarations }
      end;

    var
      Form2: TForm2;

    implementation

    {$R *.dfm}

    { TMyItem }

    constructor TMyItem.Create(aName: string);
    begin
      fname := aName;
    end;

    { TMyItemList }

    function TMyItemList.Add(Obj: TMyItem): Integer;
    begin
      Result := inherited Add (Obj);
    end;

    procedure TMyItemList.SetObject(Index: Integer; Item: TMyItem);
    begin
      inherited SetItem (Index, Item);
    end;

    function TMyItemList.GetObject(Index: Integer): TMyItem;
    begin
      Result := inherited GetItem (Index) as TMyItem;
    end;

    procedure TMyItemList.Insert(Index: Integer; Obj: TMyItem);
    begin
      inherited Insert(Index, Obj);
    end;

    {TForm2}

    procedure TForm2.FormCreate(Sender: TObject);
    begin
      TestGenerics;
      TestRegular;
    end;

    procedure TForm2.TestRegular;
    var
     tmp: TMyItemList;
    begin
     tmp := TMyItemList.Create;
     tmp.Add(TMyItem.Create('1'));
     tmp.Add(TMyItem.Create('2'));
     tmp.Free;
    end;

    procedure TForm2.TestGenerics;
    var
     tmp: TObjectList<TMyItem>;
    begin
     tmp := TObjectList<TMyItem>.Create;
     tmp.Add(TMyItem.Create('1'));
     tmp.Add(TMyItem.Create('2'));
     tmp.Free;
    end;

    end.

【问题讨论】:

  • 应该可以编写一个调试器助手或任何它被称为动态查询对象的类然后开始工作的东西。不过,我只是停止使用无类型版本。其实我已经有了!
  • 非常感谢您的评论!你能帮忙提一个调试器助手的例子吗?
  • In fact I already have!,你的意思是你已经切换到泛型集合了吗?您能谈谈您对演出的看法吗?
  • 通用版本的性能更好,因为没有动态转换。
  • 其实是Debugger Visualizer

标签: delphi debugging generics inspector tobjectlist


【解决方案1】:

我认为您无法改进鼠标光标悬停提示中出现的内容。

但是,您可以在调试窗口中使用类型转换,就像在源代码中一样。

例如,您可以在评估窗口 (Ctrl F7) 中将 tmp 变量类型转换为 TObjectList(tmp) 或在类型转换的变量上创建一个监视 (Ctrl F5)。

【讨论】:

  • !LachlanG:非常感谢您的评论!你说的对!在评估窗口中写TObjectList(tmp),切换到属性选项卡,我可以得到计数。你能帮忙提一下我是否也可以检查常规 TObjectList 中的项目吗?
  • @Xichen Li - 只需将 Evaluate Window 中的类型转换更改为 TMyItemList(tmp),您应该可以将各个项目引用为 TMyItemList(tmp)[0].NameTMyItemList(tmp)[1].Name。如果这不起作用,请多输入一点:TMyItem(TMyItemList(tmp).[0].Name
  • @Ken:非常感谢您的建议!使用TMyItemList(tmp)[0].Name 效果很好!
【解决方案2】:

Debugger Visualizers 允许您自定义调试器的可视化功能。我从未使用过它们,但据我了解,您可以将它们与一些 RTTI 结合起来,并提供有关 TObject 实例的更丰富的信息。

但是,在这里使用泛型是您想要的。它提供了具有明显优势的编译时类型。我只是这样做。

【讨论】:

  • 非常感谢您的建议!
  • 我尝试学习 Open Tools API 来创建定制的调试器可视化工具。但看起来我必须为每个单线态 TObjectList 后代创建它。正如你所说,泛型可能是最好的选择。
  • 我确信它可以为 TObjectList 完成一次,让 RTTI 完成繁重的工作。但仿制药赢了!
  • 感谢您提到可以做到!那我应该过一段时间再试试。
猜你喜欢
  • 1970-01-01
  • 2012-12-04
  • 2013-02-06
  • 1970-01-01
  • 1970-01-01
  • 2022-01-03
  • 1970-01-01
  • 1970-01-01
  • 2012-04-12
相关资源
最近更新 更多