Wednesday, May 30, 2007

DN4DP#11: The try-finally-Free pattern

This post continues the series of The Delphi Language Chapter teasers from Jon Shemitz’ .NET 2.0 for Delphi Programmers book. Last time we covered class helpers and why they were invented. This post looks in more detail at the TObjectHelper class helper and the Free method.

Note that I do not get any royalties from the book and I highly recommend that you get your own copy – for instance at Amazon.

"The try-finally-Free pattern

The Borland.Delphi.System unit declares the TObjectHelper class helper that injects methods like Free and ClassName into all classes (including FCL classes). The Free method is special and implements deterministic disposing of unmanaged resources by calling IDispose.Disposable (if it is implemented by the class).

procedure TObjectHelper.Free;
begin
if (Self <> nil) and (Self is IDisposable) then
begin
// ...
(Self as IDisposable).Dispose;
end;
end;

To complete the cycle, the compiler effectively transforms an overridden Destroy destructor into an implementation of the IDisposable interface.

type 
TFoo = class
public
destructor Destroy; override;
end;

This is transformed by the compiler into the equivalent of

type 
TFoo = class(TObject, IDisposable)
public
procedure IDisposable.Dispose = Destroy;
procedure Destroy;
end;

This means that the traditional Delphi pattern of calling Free to clean up and writing a destructor to implement the clean up will have the same semantics in .NET. The difference is that actually deallocating the memory allocated by objects is deferred to the garbage collector. It can be argued that if all your destructors do is freeing the memory of other nested objects, calling Free and implementing destructors in .NET is pure overhead. The counter-argument is that if any of the sub-objects implements a resource releasing IDisposable.Dispose (now or in the future), this is the correct way of doing things. "

No comments:

Post a Comment

Comments are moderated - spam and non-relevant links to will be deleted.