首页 > 解决方案 > 我不断收到“无效的类类型转换”错误,我不知道为什么

问题描述

我试图在关闭表单时释放一个组件,但是当我运行此代码时,我不断收到“无效的类类型转换”错误,我不知道为什么。

procedure TfrmMenu.FormHide(Sender: TObject);
var
  I: Integer;
  sID: String;
begin
  I := 0;
  repeat
    Inc(I);
    with dmMenu.qryMcDonalds do
    begin
      SQL.Text := 'Select ItemID FROM tblMenu WHERE ItemID LIKE "' + IntToStr
        (I) + '%"';
      Open;
    end;
    sID := dmMenu.qryMcDonalds.Fields[0].AsString;

    if (Components[I] as TImage).Name = 'imgd' + sID then
    begin (Components[I] as TImage)
      .Free;
    end;

     if (Components[I] as TLabel).Name = 'lbld' + sID then
      begin (Components[I] as TLabel)
      .Free;
      end;
  until I = ComponentCount - 1;
end;

标签: delphierror-handlingdelphi-2010

解决方案


你的问题出在这部分:

    if (Components[I] as TImage).Name = 'imgd' + sID then
    begin (Components[I] as TImage)
      .Free;
    end;

     if (Components[I] as TLabel).Name = 'lbld' + sID then
      begin (Components[I] as TLabel)
      .Free;
      end;

Delphi 中的as强制转换基本上是断言强制转换:您是在说您确定它将是那种类型,如果不是,则引发无效的强制转换异常。现在,您断言每个单独的组件都将是 aTImage和 a TLabel,这显然永远不会是真的。

您可能真正想做的是:

    if (Components[I] is TImage) and (Components[I].Name = 'imgd' + sID) then
    begin
        Components[I].Free;
    end;

     if (Components[I] is TLabel) and (Components[I].Name = 'lbld' + sID) then
     begin
         Components[I].Free;
      end;

您实际上并不需要其中的演员表,因为Name它是基类上的一个属性。TComponent

编辑:安德烈亚斯在评论中指出的几点:

首先,如果您正在迭代一个集合并从中删除项目,您需要向后工作。 为了说明原因,让我们从这个列表中删除所有偶数:

[1, 3, 5, 2, 4, 6]

所以如果我们做这样的事情:

for i := 0 to list.Length - 1 do
begin
   if list[i] mod 2 = 0 then
   begin
      list.Remove(i);
   end;
end;

在前三个迭代中,我们发现数字不是偶数。到目前为止,一切都很好。但是在#4,(i = 3),我们有一个偶数。我们将其从列表中删除。现在的名单是[1, 3, 5, 4, 6]。现在我们i增加到 4。 这个新列表中的元素 #4 是 6;我们跳过了4!这仅在您倒数时才有效,因为删除内容只会重新排列您已经完成的工作,而不是您还剩下要做的工作。

此外,Components表单上的集合将包含所有组件,无论它们在表单设计器中设置的顺序如何。您调用的任何图像都不太可能imgd1成为该集合中的组件 #1。如果您正在寻找名称以数字开头imgdlbld后跟数字的这些类型的任何组件,您可能需要编写一个自定义名称验证函数来检查它。但是检查数字是否相同I或多或少是无用的,因为I这里完全是任意的。


推荐阅读