Why should I not use “with” in Delphi?

2019-01-04 13:55发布

I've heard many programmers, particularly Delphi programmers scorn the use of 'with'.

I thought it made programs run faster (only one reference to parent object) and that it was easier to read the code if used sensibly (less than a dozen lines of code and no nesting).

Here's an example:

procedure TBitmap32.FillRectS(const ARect: TRect; Value: TColor32);
begin
  with ARect do FillRectS(Left, Top, Right, Bottom, Value);
end;

I like using with. What's wrong with me?

11条回答
淡お忘
2楼-- · 2019-01-04 14:30

It would be great if the with statement would be extented the following way:

with x := ARect do
begin
  x.Left := 0;
  x.Rigth := 0;
  ...
end;

You wouldn't need to declare a variable 'x'. It will be created by the compiler. It's quick to write and no confusion, which function is used.

查看更多
做个烂人
3楼-- · 2019-01-04 14:32

At work we give points for removing Withs from an existing Win 32 code base because of the extra effort needed to maintain code that uses them. I have found several bugs in a previous job where a local variable called BusinessComponent was masked by being within a With begin block for an object that a published property BusinessComponent of the same type. The compiler chose to use the published property and the code that meant to use the local variable crashed.

I have seen code like

With a,b,c,d do {except they are much longer names, just shortened here) begin i := xyz;
end;

It can be a real pain trying to locate where xyz comes from. If it was c, I'd much sooner write it as

i := c.xyz;

You think it's pretty trivial to understand this but not in a function that was 800 lines long that used a with right at the start!

2

You can combine with statements, so you end up with

with Object1, Object2, Object3 do
begin
  //... Confusing statements here
end

And if you think that the debugger is confused by one with, I don't see how anyone can determine what is going on in the with block

1

It permits incompetent or evil programmers to write unreadble code. Therefor, only use this feature if you are neither incompetent nor evil.

  • 3
    And if you can guarantee that your code will never be read or edited by a programmer less competant than yourself. – Richard A Nov 4 '08 at 2:15
  • 2
    And if you are sufficiently competent always to use with perfectly correctly: you would simply declare a local variable alias instead, because that way the code would be explicit and far more readable in the future, at the cost of a few extra seconds of typing now. – Disillusioned Jun 8 '12 at 16:38
1
... run faster ...

Not necessarily - your compiler/interpreter is generally better at optimizing code than you are.

I think it makes me say "yuck!" because it's lazy - when I'm reading code (particularly someone else's) I like to see explicit code. So I'd even write "this.field" instead of "field" in Java.

-1

We've recently banned it in our Delphi coding stnadards.

The pros were frequently outweighing the cons.

That is bugs were being introduced because of its misuse. These didn't justify the savings in time to write or execute the code.

Yes, using with can led to (mildly) faster code execution.

In the following, foo is only evaluated once:

with foo do
begin
  bar := 1;
  bin := x;
  box := 'abc';
end

But, here it is evaluated three times:

foo.bar := 1;
foo.bin := x;
foo.box := 'abc';
  • 1
    Are you sure about that? I would be very surprised if the compiler wasn't smart enough to optimize the second case into the first case. – Blorgbeard Oct 19 '08 at 19:54
  • 1
    Quite sure. Delphi is the primary env. at my day job and I'm intimately familiar with it. Pascal's nature makes optimization easy due to pervasive static typing but the optimizations the compiler performs are by now technologically a few generations behind. This compiler is not as smart as we are. – Mihai Limbășan Oct 19 '08 at 20:23
  • 8
    If you store foo in a local variable, then you'll be getting the equivalent level of performance as "with". – Barry Kelly Oct 19 '08 at 20:27
  • That's perfectly true. The performance hit is there when accessing function-type properties (function call, non-inlined pre-Delphi10) and instance variables (vtable lookup.) If you use a local and take care to place the accesses one after the other, it's as fast as the with clause. – Mihai Limbășan Oct 20 '08 at 11:17
  • 4
    If Foo is a function, or a property called by a GetFoo method, the compiler MUST execute the function each time, as it may have other side effects (generally bad design, but it does happen). – Gerry Coll Nov 23 '08 at 20:43
-1

For Delphi 2005 is exist hard error in with-do statement - evaluate pointer is lost and repace with pointer up. There have to use a local variable, not object type directly.

  • 8
    Can you rephrase your answer? Its very difficult to understand what you are trying to say. – Kenneth Cochran Jul 27 '10 at 17:42

protected by Johan Jul 7 '16 at 21:39

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.

查看更多
你好瞎i
4楼-- · 2019-01-04 14:39

There's nothing wrong with it as long as you keep it simple and avoid ambiguities.

As far as I'm aware, it doesn't speed anything up though - it's purely syntactic sugar.

查看更多
孤傲高冷的网名
5楼-- · 2019-01-04 14:43

This debate happens in Javascipt a lot too.

Basically, that With syntax makes it very hard to tell at a glance which Left/Top/etc property/method you're calling on.You could have a local variable called Left, and a property (it's been a while since I've done delphi, sorry if the name is wrong) called Left, perhaps even a function called Left. Anyone reading the code who isn't super familiar with the ARect structure could be very very lost.

查看更多
在下西门庆
6楼-- · 2019-01-04 14:43

What you save in typing, you lose in readability. Many debuggers won't have a clue what you're referring to either so debugging is more difficult. It doesn't make programs run faster.

Consider making the code within your with statement a method of the object that you're refering to.

查看更多
女痞
7楼-- · 2019-01-04 14:43

It's primarily a maintenance issue.

The idea of WITH makes reasonable sense from a language point of view, and the argument that it keeps code, when used sensibly, smaller and clearer has some validity. However the problem is that most commercial code will be maintained by several different people over it's lifetime, and what starts out as a small, easily parsed, construct when written can easily mutate over time into unwieldy large structures where the scope of the WITH is not easily parsed by the maintainer. This naturally tends to produce bugs, and difficult to find ones at that.

For example say we have a small function foo which contains three or four lines of code which have been wrapped inside a WITH block then there is indeed no issue. However a few years later this function may have expanded, under several programmers, into 40 or 50 lines of code still wrapped inside a WITH. This is now brittle, and is ripe for bugs to be introduced, particularly so if the maintainer stars introducing additional embedded WITH blocks.

WITH has no other benefits - code should be parsed exactly the same and run at the same speed (I did some experiments with this in D6 inside tight loops used for 3D rendering and I could find no difference). The inability of the debugger to handle it is also an issue - but one that should have been fixed a while back and would be worth ignoring if there were any benefit. Unfortunately there isn't.

查看更多
登录 后发表回答
相关问题
查看全部
相关文章
查看全部
收藏的人(6)