Delphi 什么是;“免费”;你在德尔福做什么?
我找到了以下代码段:Delphi 什么是;“免费”;你在德尔福做什么?,delphi,pascal,Delphi,Pascal,我找到了以下代码段: 只是好奇,free语句/函数(介于finally和end之间)在这里做什么?Google没有帮助。Free调用对象的析构函数,并释放对象实例占用的内存。这是对TObject.Free的调用,基本上定义为: if self <> nil then self.Destroy; 如果为自零,则 自我毁灭; 它在with语句中创建的未命名TClipper对象上执行 这是一个很好的例子,说明了为什么不应该将与一起使用。它会使代码更难阅读。我对Delphi一无所知,
只是好奇,
free
语句/函数(介于finally
和end
之间)在这里做什么?Google没有帮助。Free调用对象的析构函数,并释放对象实例占用的内存。这是对TObject.Free的调用,基本上定义为:
if self <> nil then
self.Destroy;
如果为自零,则
自我毁灭;
它在with
语句中创建的未命名TClipper对象上执行
这是一个很好的例子,说明了为什么不应该将
与
一起使用。它会使代码更难阅读。我对Delphi一无所知,但我认为它释放了TClipper使用的资源,就像C#中的using语句一样。这只是猜测而已……任何手动创建的对象都必须调用free以在对象创建时释放使用后的定位内存。TClipper对象是一个桌面内容创建、捕获和管理工具。因此,它是一种带有Clipper的Delphi连接对象。create(对象创建)在try finally end中处理station什么意思,如果与Clipper的连接不成功,则对象TClipper将不会创建,并且在try finally end之后无法释放语句。代码
with TClipper.Create do
try
AddPolygon(subject, ptSubject);
AddPolygon(clip, ptClip);
Execute(ctIntersection, solution);
finally
free;
end
是的缩写
with TClipper.Create do
begin
try
AddPolygon(subject, ptSubject);
AddPolygon(clip, ptClip);
Execute(ctIntersection, solution);
finally
free;
end;
end;
TClipper.Create
创建一个类型为TClipper
的对象,并返回该对象,而在大多数语言中使用的with
语句允许您访问此TClipper对象的方法和属性,而无需使用NameOfObject.MethodOrProperty
语法
(一个更简单的例子:
MyPoint.X := 0;
MyPoint.Y := 0;
MyPoint.Z := 0;
MyPoint.IsSet := true;
可以简化为
with MyPoint do
begin
X := 0;
Y := 0;
Z := 0;
IsSet := true;
end;
)
但在您的情况下,您永远不需要将TClipper对象声明为变量,因为您可以创建它,并通过with
构造访问它的方法和属性
所以你的代码几乎等同于
var
Clipper: TClipper;
Clipper := TClipper.Create;
Clipper.AddPolygon(subject, ptSubject);
Clipper.AddPolygon(clip, ptClip);
Clipper.Execute(ctIntersection, solution);
Clipper.Free;
第一行,Clipper:=TClipper.Create
,创建一个TClipper
对象。以下三行处理该对象,然后Clipper.Free
销毁该对象,释放RAM,可能还有TClipper
对象使用的CPU时间和操作系统资源
但是上面的代码并不好,因为如果在AddPolygon
或Execute
中发生错误(创建异常),那么将永远不会调用Clipper.Free
,因此内存泄漏。为了防止这种情况,Delphi使用了try…finally…end
构造:
Clipper := TClipper.Create;
try
Clipper.AddPolygon(subject, ptSubject);
Clipper.AddPolygon(clip, ptClip);
Clipper.Execute(ctIntersection, solution);
finally
Clipper.Free;
end;
即使创建了异常,并且即使调用Exit
,在try
和finally
之间的代码也保证运行
梅森的意思是,有时带有
结构的可以是一幅画在。。。大脑,因为标识符冲突。例如,考虑
MyObject.Caption := 'My test';
如果您将其写入带有
构造的中,即
with MyObect do
begin
// A lot of code
Caption := 'My test';
// A lot of code
end;
那你可能会感到困惑。实际上,大多数情况下,Caption:=
更改当前表单的标题,但是现在,由于with
语句,它将更改MyObject的标题
更糟糕的是,如果
MyObject.Title := 'My test';
MyObject没有Caption
属性,您忘记了这一点(并且认为该属性被称为Caption
),然后
甚至不会编译,而
with MyObect do
begin
// A lot of code
Caption := 'My test';
// A lot of code
end;
将编译得很好,但它不会达到您期望的效果
此外,类似于
with MyObj1, MyObj2, ..., MyObjN do
或使用
语句嵌套,如中所示
with MyConverter do
with MyOptionsDialog do
with MyConverterExtension do
..
会产生很多冲突
用
声明为辩护
我注意到,几乎有一种共识(至少在这篇文章中是这样),那就是with
语句是弊大于利的。虽然我意识到潜在的混乱,并且已经为之倾倒了好几次,但我不能同意。仔细使用with
语句可以使代码看起来更漂亮。这就减少了由于错误而引起混乱的风险
例如:
MyPoint.X := 0;
MyPoint.Y := 0;
MyPoint.Z := 0;
MyPoint.IsSet := true;
比较
var
verdata: TVerInfo;
verdata := GetFileVerNumbers(FileName);
result := IntToStr(verdata.vMajor) + '.' + IntToStr(verdata.vMinor) + '.' + IntToStr(verdata.vRelease) + '.' + IntToStr(verdata.vBuild);
与
绝对没有混淆的风险,而且在最后一种情况下,我们不仅保存了一个临时变量,而且可读性更高
或者这个非常非常标准的代码呢:
with TAboutDlg.Create(self) do
try
ShowModal;
finally
Free;
end;
究竟哪里有造成混乱的风险?从我自己的代码中,我可以给出数百个带有
语句的示例,所有这些都简化了代码
此外,如上所述,只要您知道自己在做什么,使用时根本没有风险。但是,如果您想在上面的示例中将with
语句与MyObject
一起使用,该怎么办:那么,在with
语句中,Caption
等于MyObject.Caption
。那么,您如何更改表单的标题呢?简单
with MyObject do
begin
Caption := 'This is the caption of MyObject.';
Self.Caption := 'This is the caption of Form1 (say).';
end;
with的另一个有用之处是处理需要花费大量时间执行的属性或函数结果
要使用上面的TClipper示例,假设您有一个TClipper对象列表,其中包含一个慢速方法,该方法返回特定选项卡页的裁剪器
理想情况下,您应该只调用此getter一次,这样您就可以使用显式局部变量,或者使用with使用隐式局部变量
var
Clipper : TClipper;
begin
Clipper := ClipList.GetClipperForTab(TabSheet);
Clipper.AddPolygon(subject, ptSubject);
Clipper.AddPolygon(clip, ptClip);
Clipper.Execute(ctIntersection, solution);
end;
或
begin
with ClipList.GetClipperForTab(TabSheet)do
begin
AddPolygon(subject, ptSubject);
AddPolygon(clip, ptClip);
Execute(ctIntersection, solution);
end;
end;
begin
with ClipList.GetClipperForTab(TabSheet) do
if (X = 0) and (Height = 0) and .... then
AddPolygon(subject, ptSubject);
end;
在这样的情况下,两种方法都可以,但在某些情况下,通常在复杂条件下,使用a可以更清晰
var
Clipper : TClipper;
begin
Clipper := ClipList.GetClipperForTab(TabSheet);
if (Clipper.X = 0) and (Clipper.Height = 0) and .... then
Clipper.AddPolygon(subject, ptSubject);
end;
或
begin
with ClipList.GetClipperForTab(TabSheet)do
begin
AddPolygon(subject, ptSubject);
AddPolygon(clip, ptClip);
Execute(ctIntersection, solution);
end;
end;
begin
with ClipList.GetClipperForTab(TabSheet) do
if (X = 0) and (Height = 0) and .... then
AddPolygon(subject, ptSubject);
end;
归根结底是个人品味的问题。我通常只使用范围非常窄的,并且从不嵌套它们。通过这种方式,它们是减少barfcode的有用工具 如果“with”像一些海报所暗示的那样邪恶,他们能解释一下吗
1.为什么Borland创建了这种语言结构,以及
2.为什么他们(Borland/Emba)