Arthur Hmayakyan
Arthur Hmayakyan

Reputation: 33

Please, explain what does the following line of "with.. do" represent

In the code: pbOut is a TPaintBox.

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

The question is, i want to understand what does the comma in with.. do structure do? Is it the same as writing with pbOut.Canvas.Font do or not?

Upvotes: 1

Views: 225

Answers (2)

LU RD
LU RD

Reputation: 34899

Look into documentation:

A with statement is a shorthand for referencing the fields of a record or the fields, properties, and methods of an object. The syntax of a with statement is:

with obj do statement

or:

with obj1, ..., objn do statement

where obj is an expression yielding a reference to a record, object instance, class instance, interface or class type (metaclass) instance, and statement is any simple or structured statement. Within the statement, you can refer to fields, properties, and methods of obj using their identifiers alone, that is, without qualifiers.

When multiple objects or records appear after with, the entire statement is treated like a series of nested with statements. Thus:

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

is equivalent to:

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

In this case, each variable reference or method name in statement is interpreted, if possible, as a member of objn; otherwise it is interpreted, if possible, as a member of objn1; and so forth. The same rule applies to interpreting the objs themselves, so that, for instance, if objn is a member of both obj1 and obj2, it is interpreted as obj2.objn.

Since a with statement requires a variable or a field to operate upon, using it with properties can be tricky at times. A with statement expects variables it operates on to be available by reference.


Generally using with is a recipe for disaster, since by the look of it, it is difficult to know if a statement refers to one of the with blocks (and which one) or an outer scope.


To answer the question,

Is it the same as writing with pbOut.Canvas.Font do or not?

If you only want to access the Font properties it is the same, but not if you want to access other members of pbOut.Canvas.

For yours and others sake, do not use with statements at all.

Upvotes: 5

Disillusioned
Disillusioned

Reputation: 14832

The comma is simply a separator for a list of things to 'scope to' using with.

As to your question, strictly speaking: it depends...

You might make the assumption that pbOut.Canvas always has a Font property (because you know TCanvas has a Font property). But nothing forces a Canvas variable to be of the TCanvas type, so you actually have to consider 2 possibilities.

In your case the first possibility explained below most likely applies, but it's important to be aware of the other.

As to your specific question:

Is it the same as writing with pbOut.Canvas.Font do or not?

It's almost the same, but not quite. That doesn't expose pbOut.Canvas, which the original code does.


Possibility 1

If Font is a member of pbOut.Canvas, then the statement is equivalent to:

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

Here you are able to reference members of either pbOut.Canvas or pbOut.Canvas.Font directly; without fully qualifying the reference.

Any members in both pbOut.Canvas and pbOut.Canvas.Font that have have the same identifier would clash. The compiler will favour the inner with item. This means you would still have to fully qualify the pbOut.Canvas member to access it.


Possibility 2

On the other hand, if Font is not an accessible member of pbOut.Canvas, then the statement is equivalent to:

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

Similar to the previous construct, you can access members of either pbOut.Canvas or Font directly; without fully qualifying the reference.


I must point out that the with statement is not really a useful construct.

  • It leads to confusing, difficult to read code because you always have to consider what an unqualified identifier really refers to.
  • There also a risk that adding/removing/renaming members in an existing object or record type might unexpectedly break existing code. Any code using with on instance of the modified type might unexpectedly scope differently.
  • The with list form in your question is even worse than single with because of the added trickery covered in my answer.

The with statement saves a small amount of code to more explicitly qualify certain identifiers; i.e. minimal "typing" savings, but at a great cost. So it is advised to not use with.

Upvotes: 10

Related Questions