Delphi 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 := 定位(_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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
这是 D2010 中的一个已知错误,已在 QualityCentral 中报告并已修复在 XE 中。
This is a known bug in D2010 which has been reported in QualityCentral and fixed in XE.
尝试在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.此问题是由意外的调试器或编译器行为引起的,此类行为是由 Delphi 2010 中的错误引起的(正如
David Heffernan
提到的,它们可能在 Delphi XE 中得到修复)。我只有一个结论:不要使用类内泛型类型,比如:
这样的事情会导致调试器或编译器做出意想不到的事情。该代码可以正确编译并运行。但就我而言,随着单位增长代码变得不稳定,它迫使我进行一些代码重构。
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:
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.
您是否尝试过使用新的 VCL 表单应用程序(包括您提供的代码)?
我做了...
1-设置断点不会做任何事情(也没有坏处),因为你必须读取你的项目才能调用 get(_id)
2-我为此添加了一行:
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:
3- the breakpoint worked as expected, without any exception
So I'm guessing there is something else going on....