我在这里找到了以下代码片段:
with TClipper.Create do
try
AddPolygon(subject, ptSubject);
AddPolygon(clip, ptClip);
Execute(ctIntersection, solution);
finally
free;
end
Run Code Online (Sandbox Code Playgroud)
只是很好奇,free
声明/功能(在finally
和之间end
)做了什么?谷歌没有帮助.
And*_*and 23
代码
with TClipper.Create do
try
AddPolygon(subject, ptSubject);
AddPolygon(clip, ptClip);
Execute(ctIntersection, solution);
finally
free;
end
Run Code Online (Sandbox Code Playgroud)
是简写
with TClipper.Create do
begin
try
AddPolygon(subject, ptSubject);
AddPolygon(clip, ptClip);
Execute(ctIntersection, solution);
finally
free;
end;
end;
Run Code Online (Sandbox Code Playgroud)
TClipper.Create
创建一个类型的对象TClipper
,并返回它,并且该with
语句与大多数语言一样,允许您在不使用NameOfObject.MethodOrProperty
语法的情况下访问此TClipper对象的方法和属性.
(一个更简单的例子:
MyPoint.X := 0;
MyPoint.Y := 0;
MyPoint.Z := 0;
MyPoint.IsSet := true;
Run Code Online (Sandbox Code Playgroud)
可以简化为
with MyPoint do
begin
X := 0;
Y := 0;
Z := 0;
IsSet := true;
end;
Run Code Online (Sandbox Code Playgroud)
)
但在您的情况下,您永远不需要将TClipper对象声明为变量,因为您创建它并可以通过with
构造访问其方法和属性.
所以你的代码几乎是平等的
var
Clipper: TClipper;
Clipper := TClipper.Create;
Clipper.AddPolygon(subject, ptSubject);
Clipper.AddPolygon(clip, ptClip);
Clipper.Execute(ctIntersection, solution);
Clipper.Free;
Run Code Online (Sandbox Code Playgroud)
第一行Clipper := TClipper.Create
创建一个TClipper
对象.以下三行与此对象一起使用,然后Clipper.Free
销毁该对象,释放RAM,还可能释放对象使用的CPU时间和OS资源TClipper
.
但上面的代码是不好的,因为如果一个错误occurrs(创建一个异常)内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;
Run Code Online (Sandbox Code Playgroud)
即使创建了异常,即使你在和之间调用,也保证运行finally
和之间的代码.end
Exit
try
finally
梅森所意味的是with
,由于标识符冲突,有时构造可能是......大脑中的油漆.例如,考虑一下
MyObject.Caption := 'My test';
Run Code Online (Sandbox Code Playgroud)
如果你在with
构造中写这个,即如果你写
with MyObect do
begin
// A lot of code
Caption := 'My test';
// A lot of code
end;
Run Code Online (Sandbox Code Playgroud)
然后你可能会感到困惑.实际上,通常会Caption :=
更改当前表单的标题,但现在,由于该with
声明,它将改变MyObject的标题.
更糟糕的是,如果
MyObject.Title := 'My test';
Run Code Online (Sandbox Code Playgroud)
并且MyObject没有Caption
属性,你忘了这个(并且认为属性被调用Caption
),然后
MyObject.Caption := 'My test';
Run Code Online (Sandbox Code Playgroud)
甚至不会编译,而
with MyObect do
begin
// A lot of code
Caption := 'My test';
// A lot of code
end;
Run Code Online (Sandbox Code Playgroud)
将编译得很好,但它不会做你期望的.
另外,构造如
with MyObj1, MyObj2, ..., MyObjN do
Run Code Online (Sandbox Code Playgroud)
或嵌套with
语句,如
with MyConverter do
with MyOptionsDialog do
with MyConverterExtension do
..
Run Code Online (Sandbox Code Playgroud)
会产生很多冲突.
With
声明我注意到,这个with
陈述几乎是一致的(至少在这个帖子中),这个陈述比邪恶更好.虽然我知道可能存在混淆,并且已经堕落了几次,但我不能同意.仔细使用该with
语句可以使代码看起来更漂亮.这减少了由于"barfcode"造成混淆的风险.
例如:
相比
var
verdata: TVerInfo;
verdata := GetFileVerNumbers(FileName);
result := IntToStr(verdata.vMajor) + '.' + IntToStr(verdata.vMinor) + '.' + IntToStr(verdata.vRelease) + '.' + IntToStr(verdata.vBuild);
Run Code Online (Sandbox Code Playgroud)
同
with GetFileVerNumbers(FileName) do
result := IntToStr(vMajor) + '.' + IntToStr(vMinor) + '.' + IntToStr(vRelease) + '.' + IntToStr(vBuild);
Run Code Online (Sandbox Code Playgroud)
绝对没有混淆的风险,我们不仅在最后一种情况下保存了一个临时变量 - 它也更具可读性.
或者这个非常非常标准的代码:
with TAboutDlg.Create(self) do
try
ShowModal;
finally
Free;
end;
Run Code Online (Sandbox Code Playgroud)
究竟混淆的风险在哪里?从我自己的代码中,我可以提供数百个with
语句示例,所有这些都是简化代码.
此外,如上所述,with
只要您知道自己在做什么,就没有任何使用风险.但是如果你想在上面的例子中使用一个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;
Run Code Online (Sandbox Code Playgroud)
另一个有用的地方是使用属性或函数结果时,需要花费很多时间来执行.
要使用上面的TClipper示例,假设您有一个TClipper对象列表,其中包含一个返回特定TabSheet 的限幅器的慢速方法.
理想情况下,你应该只把这种吸气一次,所以你可以使用一个明确的局部变量,或者使用隐含一个用.
var
Clipper : TClipper;
begin
Clipper := ClipList.GetClipperForTab(TabSheet);
Clipper.AddPolygon(subject, ptSubject);
Clipper.AddPolygon(clip, ptClip);
Clipper.Execute(ctIntersection, solution);
end;
Run Code Online (Sandbox Code Playgroud)
要么
begin
with ClipList.GetClipperForTab(TabSheet)do
begin
AddPolygon(subject, ptSubject);
AddPolygon(clip, ptClip);
Execute(ctIntersection, solution);
end;
end;
Run Code Online (Sandbox Code Playgroud)
在这种情况下,任何一种方法都可以,但在某些情况下,通常在复杂的条件下,a可以更清楚.
var
Clipper : TClipper;
begin
Clipper := ClipList.GetClipperForTab(TabSheet);
if (Clipper.X = 0) and (Clipper.Height = 0) and .... then
Clipper.AddPolygon(subject, ptSubject);
end;
Run Code Online (Sandbox Code Playgroud)
要么
begin
with ClipList.GetClipperForTab(TabSheet) do
if (X = 0) and (Height = 0) and .... then
AddPolygon(subject, ptSubject);
end;
Run Code Online (Sandbox Code Playgroud)
最终是个人品味的问题.我通常只会使用范围非常窄的with,而不会嵌套它们.以这种方式使用它们是减少barfcode的有用工具.
Mas*_*ler 15
它是对TObject.Free的调用,基本上定义为:
if self <> nil then
self.Destroy;
Run Code Online (Sandbox Code Playgroud)
它正在with
语句中创建的未命名的TClipper对象上执行.
这是你不应该使用的一个很好的例子with
.它往往使代码更难阅读.
归档时间: |
|
查看次数: |
1827 次 |
最近记录: |