2010-12-05 2 views
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 at iccDynamicObject.define() -> tmp: = locate (_id); вызовет @Project Project1.exe поднял класс исключений EVariantBadVarTypeError с сообщением «Недопустимый тип варианта». @Ошибка недопустимого варианта типа Delphi 2010

Код был протестирован в DELPHI 7, и эта проблема не возникала!

пс. код был переписан в Дельфах-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; 

Такие вещи закупать отладчик или компилятор, чтобы делать НЕОПРЕДЕЛЕННЫЕ ВЕЩИ !!! Код компилируется и работает правильно. Но в моем случае, с кодом роста Unit нестабилен и заставить меня сделать некоторый кодовый рефакторинг, только немного, но больше, чем неудобно ...

Вы Заметили :)))

+1

Если проблема была в том, что у вас был класс, вложенный в общий класс, то можете ли вы, пожалуйста, отредактировать вопрос, чтобы у кода возникла проблема, о которой вы говорите? * Конечно * код работает в Delphi 7; эта версия даже не поддерживает дженерики. – 2010-12-06 22:33:32

+0

@ эта версия даже не поддерживает дженерики @ - ничего себе, ты гениальный !!! ВАУ!!! как вы не могли понять, я написал, что проблемы возникли у GENERICS, которые присутствуют в delphi2010. пожалуйста, внимательно прочитайте в следующий раз, хорошо? – Focker 2011-01-15 22:56:56

ответ

1

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

+0

отладчик даже не может дотянуться до этого метода !!! если точка останова не установлена, код работает правильно БЕЗ любой ошибки. – Focker 2010-12-05 23:18:12

+1

Вы как бы не упомянули об этом (что указывает на то, что точка останова вызывает исключение) в вашем исходном описании. – dthorpe 2010-12-06 18:47:15

0

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

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

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

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

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

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; 

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

Смежные вопросы