我在Delphi中使用多年的技术已不再适用,因为我创建的表单在发布之后并未设置为nil。这是一些示例代码:
type
TAboutForm = class(TForm);
end;
function ShowAboutForm: TModalResult;
function ShowAboutForm2: TModalResult;
implementation
var
FAboutForm: TAboutForm;
{$R *.dfm}
function AboutForm: TAboutForm;
begin
if not Assigned(FAboutForm) then
FAboutForm := TAboutForm.Create(Application);
Result := FAboutForm;
end;
function ShowAboutForm: TModalResult;
begin
with AboutForm do
try
Result := ShowModal;
finally
Release;
end;
end;
function ShowAboutForm2: TModalResult;
var
AAboutForm: TAboutForm;
begin
AAboutForm := AboutForm;
try
Result := AAboutForm.ShowModal;
finally
AAboutForm.Release;
AABoutForm := nil;
end;
end;
ShowAboutForm和ShowAboutForm2都没有第二次工作。两者都抛出访问冲突,因为任何一种方法都没有将FAboutForm设置为nil - 即使ShowAboutForm2显式地将局部变量设置为nil - 因此它不会在AboutForm中重新创建。我发现让代码工作的唯一方法是:
function ShowAboutForm3: TModalResult;
begin
fAboutForm := AboutForm;
try
Result := fAboutForm.ShowModal;
finally
fAboutForm.Release;
fAboutForm := nil;
end;
这是处理创建和发布表单的合适方式吗?除非直接引用已实现的var,否则为什么表单不会被释放?
答案 0 :(得分:9)
你的技术一直都被打破了。如果它曾经奏效,那只是偶然的。
在第一个示例中,您只是发布表单,您永远不会将其全局引用设置为nil
,因此它将指向表单对象实例所在的无效内存。
在第二个示例中,您将表单对象的本地引用设置为nil
,而不是稍后测试的全局引用。由于您使用Assigned
进行测试的引用从未设置为nil
,因此它也指向无效内存。
变量(reference)仅表示指向真实对象所在内存的指针。您可以拥有指向同一对象实例的多个指针。但是这些参考文献中的每一个都是独立的。如果您将其中一个设置为nil
或任何其他值,则其他引用仍将指向之前指向的任何值。
正如您已经发现的那样,真正的解决方案是将fAboutForm
引用设置为nil
,因为这是您使用Assigned
测试的引用。
此外,由于您使用全局变量来保留引用并在AboutForm
函数中分配该变量,因此您实际上不必在ShowAboutForm3
中使用{{1}再次分配该变量}}。
它对你的代码功能没有任何影响,它会起到同样的作用,但它有点乱。