德尔福的“免费”做什么?
我找到了以下代码片段
here:
with TClipper.Create do try AddPolygon(subject,ptSubject); AddPolygon(clip,ptClip); Execute(ctIntersection,solution); finally free; end 只是好奇,免费声明/功能(终于和结束之间)在这里做什么?谷歌没有帮助. 解决方法
代码
with TClipper.Create do try AddPolygon(subject,solution); finally free; end 是简写 with TClipper.Create do begin try AddPolygon(subject,solution); finally free; end; end; TClipper.Create创建一个TClipper类型的对象,并返回它,并且with语句(与大多数语言一样)允许您在不使用NameOfObject.MethodOrProperty语法的情况下访问此TClipper对象的方法和属性. (一个更简单的例子: 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时间和OS资源. 但是上面的代码并不好,因为如果在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; 即使创建了异常,即使在try和finally之间调用Exit,也可以保证finally和end之间的代码运行. 梅森所意味的是,由于标识符的冲突,有时构造可能是……大脑中的一个颜料.例如,考虑一下 MyObject.Caption := 'My test'; 如果你在with构造中写这个,即如果你写 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),然后 MyObject.Caption := 'My test'; 甚至不会编译,而 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 .. 会产生很多冲突. 捍卫The With Statement 我注意到,几乎有一个共识(至少在这个帖子中),with语句比邪恶更好.虽然我知道可能存在混淆,并且已经堕落了几次,但我不能同意.仔细使用with语句可以使代码看起来更漂亮.这减少了“barfcode”引起混淆的风险. 例如: 相比 var verdata: TVerInfo; verdata := GetFileVerNumbers(FileName); result := IntToStr(verdata.vMajor) + '.' + IntToStr(verdata.vMinor) + '.' + IntToStr(verdata.vRelease) + '.' + IntToStr(verdata.vBuild); 同 with GetFileVerNumbers(FileName) do result := IntToStr(vMajor) + '.' + IntToStr(vMinor) + '.' + IntToStr(vRelease) + '.' + IntToStr(vBuild); 绝对没有混淆的风险,我们不仅在最后一种情况下保存了一个临时变量 – 它也更具可读性. 或者这个非常非常标准的代码: with TAboutDlg.Create(self) do try ShowModal; finally Free; end; 究竟混淆的风险在哪里?从我自己的代码中,我可以提供数百个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; 另一个有用的地方是使用属性或函数结果时,需要花费很多时间来执行. 要使用上面的TClipper示例,假设您有一个TClipper对象列表,其中包含一个返回特定TabSheet的限幅器的慢速方法. 理想情况下,您应该只调用此getter一次,因此您可以使用显式局部变量,也可以使用隐式局部变量. var Clipper : TClipper; begin Clipper := ClipList.GetClipperForTab(TabSheet); Clipper.AddPolygon(subject,solution); end; 要么 begin with ClipList.GetClipperForTab(TabSheet)do begin AddPolygon(subject,solution); end; 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 if (X = 0) and (Height = 0) and .... then AddPolygon(subject,ptSubject); end; 最终是个人品味的问题.我通常只会使用范围非常窄的with,而不会嵌套它们.以这种方式使用它们是减少barfcode的有用工具. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |