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;

在 iccDynamicObject.define() -> tmp := locate(_id); 处设置 DELPHI 2010 断点 将导致@ 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;

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

你被注意到了:)))

4

4 回答 4

5

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

于 2010-12-06T05:53:35.753 回答
1

这个问题是由意外的调试器或编译器行为引起的,这种行为是由 Delphi 2010 中的错误引起的(它们可能在 Delphi XE 中得到修复,David Heffernan如前所述)。

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

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;

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

于 2010-12-06T14:49:25.140 回答
1

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

于 2010-12-05T23:12:01.647 回答
0

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

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

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

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

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

于 2010-12-05T23:46:33.480 回答