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 でテストされており、この問題は発生しませんでした!

ps。コードは、問題を示すためにクラス内の型を使用せずに 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のバグが原因で発生しました(David Heffernan前述のように、Delphi XEで修正される可能性があります)。

結論は1つだけです。次のようなクラス内のジェネリック型は使用しないでください。

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 に答える