First of all, sorry for the lengthy code example, but I believe it's needed to illustrate my problem.
As a debugging help I often introduce a "DebugString"-method on my objects, which returns a concise object summary. But sometimes my objects are too complex to be represented optimally in a single string, so I use stringlists. Now, I would like to use the excellent debug visualizers in Delphi to monitor my object. The way I do this is to introduce a property with a getter that rebuilds the stringlist.
This kinda works, but for every line I trace, the property gets out of scope, so I have to click the magnifying glass in the watch window again to see the value. Why is this?
To reproduce, create a new console application:
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils,
Classes;
type
TMyClass = class
private
FInternalData : array[0..4] of integer;
FDebugStringList : TStringList;
procedure RebuildDebugStringlist;
function GetDebugStringList: TStringList;
function GetDebugString : string;
public
constructor Create;
destructor Destroy; override;
procedure Scramble;
property DebugStringList : TStringList read GetDebugStringList;
property DebugString : string read GetDebugString;
end;
constructor TMyClass.Create;
begin
FDebugStringList := TStringList.Create;
end;
destructor TMyClass.Destroy;
begin
FDebugStringList.Free;
inherited;
end;
function TMyClass.GetDebugString: string;
var
I : integer;
begin
Result := 'Object state: ';
for I := 0 to 3 do
Result := Result + inttostr(FInternalData[I])+' ';
end;
function TMyClass.GetDebugStringList: TStringList;
begin
RebuildDebugStringlist;
Result := FDebugStringlist;
end;
procedure TMyClass.RebuildDebugStringlist;
var
I : integer;
begin
FDebugStringList.Clear;
FDebugStringList.Add('Object state:');
for I := 0 to 4 do
FDebugStringList.Add(inttostr(FInternalData[I]));
end;
procedure TMyClass.Scramble;
var
I : integer;
begin
for I := 0 to 4 do
FInternalData[I] := Random(100);
end;
var
vMyObj : TMyClass;
begin
vMyObj := TMyClass.Create;
try
vMyObj.Scramble;
vMyObj.Scramble;
vMyObj.Scramble;
finally
vMyObj.Free;
end;
readln;
end.
- Add watches for "vMyObj.DebugStringList" and "vMyObj.DebugString"
- Place a breakpoint on line 77 (the 2nd "vMyObj.Scramble"), and run.
- Click the magnifying glass next to the "DebugStringList" watch to get the visualizer
- Observe that the visualizer works nicely :)
- Step over the next line. The visualizer now indicates the watch is out of scope.
- Press the magnifying glass again to see the new state of the object.
Why does the visualizer say that the watch is out of scope? How can I fix this?
PS: I know I can write debug visualizers, but I use "DebugString" and "DebugStringList" in some automatic tests, and I would really like to use them in this easy fashion.
Update: I use Delphi XE
Update 2: Despite a good effort by Marjan Venema, I still have no solution to this problem. I've filed a report with Embarcadero (QC number 98062, please vote :-)). However, I suspect it will take some time for Embarcadero fix this problem, and seeing how I'm still interested in a workaround, I'll offer a small bounty. Never tried that before, so it will be interesting to se what happens :-)