Thursday, August 12, 2004

The Delphi "with" statement

I agree with Hallvard on his comments about the with statement, as well as his follow-up. One big problem I find in dealing with other coders is they would rather have syntactical sugar over using comments and formatting in their code. I suspect the reason his reader likes his version using the "with" statement is because it offsets the code in a block. There is not reason you couldn't do this:
var
  a: TForm1;
begin
  // 'a' is a local reference to the global Form1
  // which is not the current form referenced by self
  a := Form1;

  // we use 'a' here as a short hand for
  // setting a few properties
  //-------------------------
    a.foo := 123;
    a.bar := 'xyz';
    a.Caption := 'Test';

  // finished using 'a'
  a := nil;

  // now setting properties on the current form
  Caption := 'Foo Bar';
end;
You could even make a comment about using a instead of a with statement to make the code more readable and easier to debug / maintain. What really gets me about other people's comments is usually they comment the obvious, and ignore the obscure. Comments like these drive me crazy:
//------------------------
// procedure name FooBar
//------------------------
procedure FooBar;
Sometimes they even go so far as to tell me the name and types of the parameters. This is information I can easily obtain by reading the source code. It would be nice if they told me what FooBar does and what is expected in the parameters.

6 comments:

Chris Brandsma said...

Can't you people leave Dystra alone!!! I doubt the trouble with GOTO's is anywhere near the problems of WITH.

The main problem with "WITH" in Delphi is not the WITH statement itself, but it is Delphi's implementation of that leads to ambiguities.

Visual Basic also has a WITH clause that works wonderfully in the language and people love it. The syntax looks like this:

with oMyObj
.param1 = "foo"
.param2 = "bar"
end with

as apposed to Delphi's
with oMyObj
begin
param1 = "foo";
param2 = "bar";
end;

The use of the "." notation in VB makes all the diference in the world! It makes it imidiatly clear which parameter belongs to which object. Unlike Delphi's implementation, where you are never sure if the parameter belongs to the WITH object or the class the procedure is in.

Now, if you want to do something to the WITH, limit its scope. I say NO to nested WITHs. That is where everyone gets in trouble.

Also note: the C# using clause is a different animal all together. This is because it denotes object destruction, where as the VB and Delphi WITH do not.

Well, that is my 3.5 cents.

unused said...

Halvard's comment is that WITH's should generate a compiler warning if it would work outside the WITH statement. See his post for a better explination.

As much as I dislike VB (on multiple levels) I have to admit that the use of the '.' syntax is a nice improvement. How does VB handle nested WITH's, or does it even allow them?

Anonymous said...

I'm positive that most C# coders despise 'with' statements because of
bad experiences with the Delphi/Javascript-style 'ambigious' syntax. The VB-style syntax (with leading dot) is clear and unambigious so doesn't create problems.

VB allows nested 'with' statements, even though it's probably not a good idea to use them. They work like this:

With foo
'// This does stuff on foo
.Method1()
.Property1 = "blah"
With bar
'// This does stuff on bar
.Method1()
.Property1 = "blah"
End With
'// Back with foo again
.Method2()
'etc...
End With

I don't understand why most C# coders (and the language creators) are so hostile to the VB-style 'with' syntax. I consider it unambigious, clear, and a far nicer method than using ugly 'single-character' objects. I wonder, which is better to read and more structurally elegant:

ReallyLongObjectType o1 = SomeObject;
o1.DoSomething();
o1.Property = "value";
ReallyLongObjectTypeAgain o2 = SomeOtherObject;
o2.DoSomethingElse();
o2.OtherProperty = "othervalue";

Or:

with SomeObject {
.DoSomething();
.Property = "value";
}
with SomeOtherObject {
.DoSomethingElse();
.OtherProperty = "othervalue";
}

I think the latter! Do you agree?

unused said...

I agree with you Hugo. It would be nice if C# and Delphi either had a complier option to require the leading . or it would work either way.

Of course the . would only work on the nearest WITH statement, in the case of nested WITH statements.

Anonymous said...

Let's not forget WHY someone would use the WITH statement, it's not only for readability (in VB), it's also for speed.
With MyCollection(i)
.param1 = "foo"
.param2 = "bar"
end with
is much faster as
MyCollection(i).Param1 = "foo"
MyCollection(i).Param2 = "bar"
in last example, every call to MyCollection(i) has to lookup the Item, as with WITH it only looksup the item once..

Hato0be said...

There is in C# something like that. Why something like that? because this statement is used on objects witch are disposable. And its main purpose is to automatically dispose the object variabile after getting out of the statement block .If we have a disposable Collection (i.e. have a Dispose() function for freeing up allocated memory) we will have the following example

using(col = new Collection)
{
col.prop1 = 1;
col.prop2 = 2;
}

otherwise we would use

Collection col = new Collection;

col.prop1 = 1;
col.prop2 = 2;

col.Dispose();

There is some advantages, but not as good as using With