【问题标题】:Invalid variant type error Delphi 2010无效的变体类型错误 Delphi 2010
【发布时间】:2010-12-05 23:03:44
【问题描述】:
// 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() 的 DELPHI 2010 中设置断点 -> tmp := locate(_id); 将导致@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;

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

你被注意到了:)))

【问题讨论】:

  • 如果问题确实是您有一个嵌套在泛型类中的类,那么您能否编辑问题以便代码显示您所说的问题? 当然代码在 Delphi 7 中工作;该版本甚至不支持泛型。
  • @那个版本甚至不支持泛型@ - 哇,你真是天才!!!哇!!!正如你所不能理解的,我写道,delphi2010 中存在的 GENERICS 遇到了问题。拜托,下次仔细看好吗?

标签: delphi generics delphi-2010 variant


【解决方案1】:

这是 D2010 中的一个已知错误,已在 reported in QualityCentral 中修复。

【讨论】:

  • 我很不喜欢:你买了 D2010,它有一个 bug,但它只在你不能免费获得的下一个版本中修复。
  • @Remko:我要扮演魔鬼的拥护者。如果他们要修复所有的错误,比如最新版本 1 或最新版本 2,这将涉及非常重大的工程工作。大量的开发和测试。就我个人而言,尽管我希望在 2010 年修复错误,但如果我能以合理的方式解决它们,我更希望他们专注于改进主线产品(64 位是我想看到的东西)。如果向后移植修复需要从 64 位中移除,那么我不希望它完成。
  • @Dorin:每个人发布软件都知道它包含错误。事实上,这种情况对每个人(供应商和客户)来说都更好。如果您花费很长时间修复所有无关紧要的错误,那么您就剥夺了您的客户所做的重大改进。 Emb 当然不会发布低质量的代码,以便他们可以稍后修复它并收取升级费用。
  • @The Bug-Fixes as Upgrade Incentive Crowd:这一切都很好,但是假设您使用的是 Delphi 2006,并且该产品中存在一些在 2007 或 2009 中未修复的错误。让我们进一步说,除了不修复错误之外,新版本还引入了新错误或对您的代码产生不利影响的行为更改。所以你不升级 - 这将是浪费钱。然后 Embarcadero 说:如果您不升级到 Delphi 2010,那么您将失去升级到任何更高版本的权利。这就是它变得不可接受的地步,我们去年就达到了这一点。
  • @Deltics:这太难了。 XE 实际上只是错误修复。
【解决方案2】:

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

【讨论】:

  • 调试器连这个方法都进不了!!!如果没有设置断点,代码可以正常工作,没有任何错误。
  • 您在原始描述中没有提到这一点(设置断点会导致异常)。
  • @在 iccDynamicObject.define() 的 DELPHI 2010 中设置断点 -> tmp := locate(_id);会导致@再次阅读
【解决方案3】:

这个问题是由意外的调试器或编译器行为引起的,这种行为是由 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;

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

【讨论】:

    【解决方案4】:

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

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

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

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

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

    【讨论】:

    • 我想,我发现了一个问题。泛型... sh*t DElphi 在同一个单元中的泛型导致调试器做一些非常奇怪的事情:(
    • 是的,问题是由有缺陷的 delphi 泛型 (:( ) 引起的。不要使用类内泛型类型。在 main 类之外声明它们
    • @Focker。然后,我建议您构建一个小型(自给自足)示例,该示例确实显示了问题并在 QC 中提交。只有这样才能修复错误...
    • 如您所见,线程已于 1 小时前更新...包括示例。在 Delphi 2010 中你不应该做的事情。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-10-19
    • 2018-01-20
    • 2011-10-13
    • 1970-01-01
    • 2010-09-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多