Invalid variant type error Delphi 2010

扶醉桌前 提交于 2019-12-12 02:37:23

问题


// 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 :)))


回答1:


This is a known bug in D2010 which has been reported in QualityCentral and fixed in XE.




回答2:


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.




回答3:


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.




回答4:


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....



来源:https://stackoverflow.com/questions/4361853/invalid-variant-type-error-delphi-2010

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!