4

Lately, I have been noticing that anytime I use Rectangle variable with With...do statement, it doesn't work at all for some reason.

For instance:

var bounds:=new Rectangle(0,0,0,0);

with bounds do
begin
  X:=1;
  Y:=2;
  Width:=33;
  Height:=44;
end;

bounds' values remain zeros not whats in the with statement. However if I do the following, it works great.

var bounds:=new Rectangle(0,0,0,0);

bounds.X:=1;
bounds.Y:=2;
bounds.Width:=33;
bounds.Height:=44;

Is there any reason why it would do that.

ThN
  • 3,235
  • 3
  • 57
  • 115
  • 4
    Discovering that value types don't behave like reference type is a learning curve for any .NET programmer. You are updating a copy. Sloppy that the compiler doesn't warn you about that. – Hans Passant Nov 30 '11 at 19:10
  • @digitalanalog What Prism version did you use? I just tried this in the latest and it works. – Carlo Kok Dec 01 '11 at 07:20
  • 1
    @HansPassant, I wish you would explain it in detail rather than sound like a philosopher. :) – ThN Dec 09 '11 at 21:49

1 Answers1

1

What Hans Passant is trying to imply is that the "with" statement creates a copy of bounds, works on it, then throws it away. I don't have enough information to verify that, but I feel that it's unlikely - Delphi's assignment operator works by reference, so implicit shallow copies don't actually happen that often.

However, "with" statements intentionally create a special kind of variable scoping hell. You could be grabbing a field inside bounds, or you could be grabbing a field from the containing method, or you could even be grabbing a field from a previous unclosed "with" statement. Automatic refactoring can't touch a with statement. Adding a field to the class the with statement operates on can break your method.

Consider

with myLongNamedComponent.anotherLongNamedChild.pedanticRectangle do
begin
    x:=1;
    y:=2;
    width:=33;
    height:=44;
end;

This is actually better written as

var bounds := new Rectangle(0,0,0,0);
bounds.x := 1;
bounds.y := 2;
bounds.width := 33;
bounds.height := 44;
myLongNamedComponent.anotherLongNamedChild.pedanticRectangle := bounds;

TL:DR; the "with" statement is no longer considered good coding practice.

Falkreon
  • 598
  • 5
  • 14
  • Thanks for the last bit of information. Your answer is very helpful. Thank you. – ThN Jan 04 '12 at 16:40