我在代码迁移过程中遇到了Delphi 2010和Delphi Berlin(上次更新)之间的问题....我做了一个简单的代码来演示一个奇怪的行为......
我有一个使用TList(前一个)和TList(来自Generics.Collections)的应用程序我知道这段代码(下面)对你没有任何意义,但它用于演示目的
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
type
TTest = class
Name: string;
constructor Create(Nome: string);
end;
TForm1 = class(TForm)
btn1: TButton;
procedure btn1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
FList: TList;
end;
var
Form1: TForm1;
implementation
uses
System.Generics.Collections;
{$R *.dfm}
procedure TForm1.btn1Click(Sender: TObject);
var
tmpList: TList<TTest>;
begin
tmpList := TList<TTest>.Create;
tmpList.Add(TTest.Create('A'));
tmpList.Add(TTest.Create('B'));
tmpList.Add(TTest.Create('C'));
tmpList.Add(TTest.Create('D'));
tmpList.Add(TTest.Create('E'));
FList := TList(tmpList);
ShowMessage(TTest(FList[0]).Name);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
FList := TList.Create;
end;
constructor TTest.Create(Nome: string);
begin
Name := Nome;
end;
end.
Run Code Online (Sandbox Code Playgroud)
在Delphi 2010中,ShowMessage显示'A'字符,但在Delphi Berlin上它引发了Acess违规
优化的两个应用程序都设置为False
FList := TList(tmpList);
Run Code Online (Sandbox Code Playgroud)
这就是问题.演员是完全错的,因为tmpList不是TList.
您的代码仅因为强制转换而编译,但强制转换不会改变右侧对象不属于要转换的类型的事实.所有演员都会阻止编译器抱怨并将你从自己身上拯救出来.你的演员阵容是编译器的谎言,结果是运行时错误.
此代码可能适用于旧版本,但只是偶然.你的运气发生了变化.
很难知道修复建议的内容.正如你所说,代码没有多大意义.每次按下按钮,都会泄漏列表.我建议您删除所有演员表,停止使用非Generic TList并仅使用Generic列表.
该类TList<T>不能转换为/来自TList.
你不能把一个投射到另一个并且期望得到明显的结果,而不是你可以投射TForm到TButton(例如).
在Delphi中,这种形式的类型转化不加以控制,有时也被称为硬铸造.也就是说,编译器只会相信您知道自己在做什么并且只是遵守,但如果类型转换无效,则结果将是不可预测的.
对于对象引用类型(和/或接口引用)之间的转换,您可以使用as运算符使用已检查的强制转换:
FList := tmpList as TList;
Run Code Online (Sandbox Code Playgroud)
如果检查的强制转换无效(例如这是),则编译器将抛出运行时异常,提醒您错误.
在某些情况下,在特定用例中,未经检查的铸造可能是有用且安全的依赖.但是在这些特定条件之外,未经检查的强制转换最多只能信赖运气或特定的编译器行为或可能会发生变化的RTL特性.
例如,在Integer变量中存储对象引用或其他指针值的32位技巧.这些代码在重新编译为64位时可能会继续工作,但现在只是运气好而且仅在某些情况下,因为只有一部分可能的64位指针值可以安全地存储在32位整数中.
如果您的代码在两者之间成功地进行了强制转换TList,TList<T>那么它只能运气,因为当时编译器或RTL的某些特定行为.