请解释下面的“with ... do”代表什么

时间:2017-12-30 07:22:19

标签: delphi

在代码中:pbOut是一个TPaintBox。

 with pbOut.Canvas, Font do 
 begin
 ....
 end;

问题是,我想了解逗号用什么做结构呢?是否与使用pbOut.Canvas.Font写或不相同?

2 个答案:

答案 0 :(得分:10)

逗号只是一个分隔符,用于列出可以'范围内的事物列表。使用

关于你的问题,严格来说:这取决于......

您可以假设pbOut.Canvas始终具有Font属性(因为您知道TCanvas具有Font属性)。但是没有什么能使Canvas变量强制为TCanvas类型,因此您实际上必须考虑两种可能性。

在您的情况下,下面解释的第一种可能性很可能适用,但了解另一种情况非常重要。

关于你的具体问题:

  

是否与撰写with pbOut.Canvas.Font do相同?

它几乎相同,但并不完全相同。这不会公开原始代码 pbOut.Canvas

可能性1

如果FontpbOut.Canvas的成员,那么该陈述相当于:

with pbOut.Canvas do
begin
  with pbOut.Canvas.Font do 
  begin
    { See notes underneath }
  end;
end;

在这里,您可以直接引用pbOut.CanvaspbOut.Canvas.Font的成员;没有完全限定参考资料。

pbOut.CanvaspbOut.Canvas.Font中具有相同标识符的所有成员都会发生冲突。编译器将支持内部with项。这意味着您仍然必须完全限定pbOut.Canvas成员才能访问它。

可能性2

另一方面,如果Font pbOut.Canvas的可访问成员,则该语句相当于:

with pbOut.Canvas do
begin
  with Font do 
  begin
    { See notes underneath }
  end;
end;

与之前的构造类似,您可以直接访问pbOut.CanvasFont的成员;没有完全限定参考资料。

我必须指出 with 语句实际上并不是一个有用的构造。

  • 这导致令人困惑,难以阅读的代码,因为您始终必须考虑 所指的
  • 在现有对象或记录类型中添加/删除/重命名成员可能会意外破坏现有代码。在修改后的类型的实例上使用 with 的任何代码可能会出乎意料地区别不同。
  • 您的问题中的列表形式甚至比使用的单个更差,因为我的答案中包含了额外的诡计。

with 语句会保存少量代码,以更明确地限定某些标识符;即最小的打字"节省,但成本很高。因此建议不要将一起使用。

答案 1 :(得分:5)

查看documentation

  

with语句是引用记录字段或对象的字段,属性和方法的简写。 with语句的语法是:

with obj do statement
     

或:

with obj1, ..., objn do statement
     

其中obj是一个表达式,表示对记录,对象实例,类实例,接口或类类型(元类)实例的引用,而statement是任何简单或结构化语句。在语句中,您可以单独使用它们的标识符来引用obj的字段,属性和方法,也就是说,没有限定符。

     

当使用后出现多个对象或记录时,整个语句将被视为一系列嵌套的语句。因此:

with obj1, obj2, ..., objn do statement
     

相当于:

 with obj1 do
   with obj2 do
     ...
     with objn do
       // statement
     

在这种情况下,如果可能,语句中的每个变量引用或方法名称都将被解释为objn的成员;否则,如果可能,将其解释为objn1的成员;等等。同样的规则适用于解释objs本身,因此,例如,如果objn是obj1和obj2的成员,则它被解释为obj2.objn。

     

由于with语句需要对变量或字段进行操作,因此将其与属性一起使用可能会很棘手。 with语句期望它操作的变量可以通过引用获得。

通常使用with是一种灾难的处方,因为从外观来看,很难知道一个语句是指with块之一(以及哪一个)或外部范围。

要回答这个问题,

  

是否与使用pbOut.Canvas.Font写或不相同?

如果您只想访问Font属性,那么它是相同的,但如果您想访问pbOut.Canvas的其他成员则不行。

为了您和其他人,请不要使用with语句。