Недопустимая ошибка типа варианта Delphi 2010 - PullRequest
0 голосов
/ 06 декабря 2010
// 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: = locate (_id);@ @ 1002 * Project Project1.exe вызовет исключительную ситуацию класса EVariantBadVarTypeError с сообщением «Неверный тип варианта». @

Код был протестирован в DELPHI 7, и с этой проблемой не сталкивалось!1007 * пс.код был переписан в стиле 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 ]

5 голосов
/ 06 декабря 2010

Это известная ошибка в D2010, о которой сообщили в QualityCentral и исправили в XE.

1 голос
/ 06 декабря 2010

Эта проблема возникла из-за неожиданного поведения отладчика или компилятора, и такое поведение было вызвано ошибками в 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;

Такие вещи могут вызвать отладчик или компилятор сделать неожиданныевещи.Код компилируется и работает правильно.Но в моем случае, когда код расширения модуля стал нестабильным, это заставило меня провести некоторый рефакторинг кода.

1 голос
/ 06 декабря 2010

Попробуйте назначить tmp := nil; в методе locate рядом с тем местом, где вы назначаете nil для результата. Если это разрешит исключение, я объясню почему.

0 голосов
/ 06 декабря 2010

Пробовали ли вы использовать новые приложения VCL Forms, включая предоставленный вами код?
Я сделал ...

1 - установка точки останова ничего не делает (также не причиняет вреда), потому что вы должны прочитать свой элемент, чтобы вызвать get (_id)
2- Я добавил строку на этот счет:

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

3 - точка останова работала, как и ожидалось, без каких-либо исключений

Так что я предполагаю, что происходит что-то еще ...

...