Reputation: 215
// interface
iccItem =
class
ID : String;
DATA : Variant;
constructor Create( _id : String; _data : Variant);
end;
iccDynamicObject =
class
private
FItems : TList;
function locate( _id : String) : iccItem;
public
constructor Create();
destructor Destroy(); override;
public
procedure define( _id : String; _dta : Variant);
//function get( _ndx : DWORD) : Variant; overload;// link to original data
function get( _id : String) : Variant; overload;
public
property Items[_id : String] : Variant read get write define; default;
end;
// implementation
{ iccDynamicObject }
constructor iccItem.Create( _id : String; _data : Variant);
begin
ID := _id;
DATA := _data;
end;
function iccDynamicObject.locate( _id : String) : iccItem;
var ndx : integer;
tmp : iccItem;
begin
result := nil;
for ndx := 0 to FItems.Count - 1 do
begin
tmp := iccItem( FItems[ndx]);
if tmp.ID = _id
then begin
result := tmp;
exit;
end;
end;
end;
constructor iccDynamicObject.Create();
begin
FItems := TList.Create();
end;
destructor iccDynamicObject.Destroy();
begin
{$MESSAGE 'clear here'}
FItems.Destroy();
inherited;
end;
procedure iccDynamicObject.define( _id : String; _dta : Variant);
var tmp : iccItem;
begin
tmp := locate( _id);
if tmp = nil
then FItems.Add( iccItem.Create( _id, _dta) )
else tmp.DATA := _dta;
end;
//function iccDynamicObject.get( _ndx : DWORD) : Variant;
//begin
// result.vPointer := nil;
//end;
function iccDynamicObject.get( _id : String) : Variant;
var tmp : iccItem;
begin
tmp := locate( _id);
if tmp = nil
then result.vaNull := true
else result := locate( _id).DATA;
end;
// using
procedure TForm1.FormCreate(Sender: TObject);
var c : iccDynamicObject;
begin
c := iccDynamicObject.Create;
c['asd'] := 123;
c.Destroy;
end;
Set breakpoint in DELPHI 2010 at iccDynamicObject.define() -> tmp := locate( _id); will cause @Project Project1.exe raised exception class EVariantBadVarTypeError with message 'Invalid variant type'.@
Code was tested in DELPHI 7, and this problem was not encountered!
ps. code was rewritten in delphi-7 style without in-class types for demonstrating a problem...
SOLVED -> Do not use in-class generic types, such as
classDef<_type> =
class
type
// this
internalClass<_anotherType> =
class
private
FSomething : _anotherType;
end;
// or this one
internalClass2 =
class
private
FSomething : _type;
end;
private
FInternalClass : internalClass<_type>;
FInternalClass2 : internalClass;
end;
Such things will procure debugger or compiler to do UNEXCECTED THINGS!!! Code compiles and work correctly. But in my case, with Unit growth code become unstable and coerce me to make some code-refactoring, just a little, but more than inconvenient...
You are Noticed :)))
Upvotes: 0
Views: 4339
Reputation: 215
This problem occured by unexpected debugger or compiler behavior, and such behavior was caused by bugs in Delphi 2010 (they might be fixed in Delphi XE, as David Heffernan
mentioned).
I have only one conclusion: Do not use in-class generic types, such as:
classDef<_type> =
class
type
// this
internalClass<_anotherType> =
class
private
FSomething : _anotherType;
end;
// or this one
internalClass2 =
class
private
FSomething : _type;
end;
private
FInternalClass : internalClass<_type>;
FInternalClass2 : internalClass;
end;
Such things will cause the debugger or compiler to do unexpected things. The code compiles and works correctly. But in my case, with Unit growth code becoming unstable it has forced me to do some code-refactoring.
Upvotes: 1
Reputation: 612954
This is a known bug in D2010 which has been reported in QualityCentral and fixed in XE.
Upvotes: 5
Reputation: 21640
Did you try with a New VCL Forms Applications, including the code you provided?
I did...
1- setting the break point does not do anything (no harm either), because you have to read your item to call get(_id)
2- I added a line to that effect:
c['asd'] := 123;
i := c['asd']; // <=== added
c.Destroy;
3- the breakpoint worked as expected, without any exception
So I'm guessing there is something else going on....
Upvotes: 0
Reputation: 36082
Try assigning tmp := nil;
in the locate method next to where you assign nil to result. If this resolves the exception, I'll explain why.
Upvotes: 1