I found the following code snippet here:
with TClipper.Create do
try
AddPolygon(subject, ptSubject);
AddPolygon(clip, ptClip);
Execute(ctIntersection, solution);
finally
free;
end
Just curious, what does the free statement/function (between finally and end) do here? Google did not help.
The code
is shorthand for
TClipper.Createcreates an object of typeTClipper, and returns this, and thewithstatement, which works as in most languages, lets you access the methods and properties of this TClipper object without using theNameOfObject.MethodOrPropertysyntax.(A simpler example:
can be simplified to
)
But in your case, you never need to declare a TClipper object as a variable, because you create it and can access its methods and properties by means of the
withconstruct.So your code is almost equivelant to
The first line,
Clipper := TClipper.Create, creates aTClipperobject. The following three lines work with this object, and thenClipper.Freedestroys the object, freeing RAM and possibly also CPU time and OS resources, used by theTClipperobject.But the above code is not good, because if an error occurrs (an exception is created) within
AddPolygonorExecute, then theClipper.Freewill never be called, and so you have a memory leak. To prevent this, Delphi uses thetry...finally...endconstruct:The code between
finallyandendis guaranteed to run, even if an exception is created, and even if you callExit, betweentryandfinally.What Mason means is that sometimes the
withconstruct can be a paint in the … brain, because of identifier conflicts. For instance, considerIf you write this inside a
withconstruct, i.e. if you writethen you might get confused. Indeed, most often
Caption :=changes the caption of the current form, but now, due to thewithstatement, it will change the caption of MyObject instead.Even worse, if
and MyObject has no
Captionproperty, and you forget this (and think that the property is calledCaption), thenwill not even compile, whereas
will compile just fine, but it won’t do what you expect.
In addition, constructs like
or nested
withstatements as incan produce a lot of conflicts.
In Defence of The
WithStatementI notice that there almost is a consensus (at least in this thread) that the
withstatement is more evil than good. Although I am aware of the potential confusion, and have fallen for it a couple of times, I cannot agree. Careful use of thewithstatement can make the code look much prettier. And this lessens the risk of confusion due to “barfcode”.For example:
Compare
with
There is absolutely no risk of confusion, and not only do we save a temporaray variable in the last case – it also is far more readable.
Or what about this very, very, standard code:
Exactly where is the risk of confusion? From my own code I could give hundreds of more examples of
withstatements, all simplifying code.Furthermore, as have been stated above, there is no risk of using
withat all, as long as you know what you are doing. But what if you want to use awithstatement together with theMyObjectin the example above: then, inside thewithstatement,Captionis equal toMyObject.Caption. How do you change the caption of the form, then? Simple!Another place where with can be useful is when working with a property or function result that takes a non-trivial amount of time to execute.
To work with the TClipper example above, suppose that you have a list of TClipper objects with a slow method that returns the clipper for a particular TabSheet.
Ideally you should only call this getter once, so you can either use an explicit local variable, or an implicit one using with.
OR
In a case like this, either method would do, but in some circumstances, typically in complex conditionals a with can be clearer.
OR
In the end is is matter of personal taste. I generally will only use a with with a very tight scope, and never nest them. Used this way they are a useful tool to reduce barfcode.