Delphi 2010 无效变体类型错误

发布于 2024-10-06 19:19:19 字数 3234 浏览 1 评论 0原文

// 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;

在 DELPHI 2010 中的 iccDynamicObject.define() -> 设置断点tmp := 定位(_id); 会导致@Project Project1.exe引发异常类EVariantBadVarTypeError,并显示消息“无效的变体类型”。@

代码在DELPHI 7中进行了测试,没有遇到这个问题!

附:代码以 delphi-7 风格重写,没有类内类型来演示问题...

已解决 ->不要使用类内泛型类型,这样的

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;

事情会促使调试器或编译器做一些意想不到的事情! 代码编译并正常工作。但就我而言,随着单位的增长,代码变得不稳定 并强迫我进行一些代码重构,只是一点点,但非常不方便......

你被注意到了:)))

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

我爱人 2024-10-13 19:19:19

这是 D2010 中的一个已知错误,已在 QualityCentral 中报告并已修复在 XE 中。

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

把昨日还给我 2024-10-13 19:19:19

尝试在locate 方法中将nil 分配给结果的位置旁边分配tmp := nil;。如果这解决了异常,我会解释原因。

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.

温柔少女心 2024-10-13 19:19:19

此问题是由意外的调试器或编译器行为引起的,此类行为是由 Delphi 2010 中的错误引起的(正如 David Heffernan 提到的,它们可能在 Delphi XE 中得到修复)。

我只有一个结论:不要使用类内泛型类型,比如:

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;

这样的事情会导致调试器或编译器做出意想不到的事情。该代码可以正确编译并运行。但就我而言,随着单位增长代码变得不稳定,它迫使我进行一些代码重构。

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.

给我一枪 2024-10-13 19:19:19

您是否尝试过使用新的 VCL 表单应用程序(包括您提供的代码)?
我做了...

1-设置断点不会做任何事情(也没有坏处),因为你必须读取你的项目才能调用 get(_id)
2-我为此添加了一行:

c['asd'] := 123;
i := c['asd'];   // <=== added
c.Destroy;

3-断点按预期工作,没有任何异常

所以我猜测还有其他事情发生......

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文