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)