The Wiert Corner – irregular stream of stuff

Jeroen W. Pluimers on .NET, C#, Delphi, databases, and personal interests

  • My badges

  • Twitter Updates

  • My Flickr Stream

  • Pages

  • All categories

  • Enter your email address to subscribe to this blog and receive notifications of new posts by email.

    Join 1,763 other followers

Delphi – bizarre use of class helpers to circumvent ‘with’

Posted by jpluimers on 2009/04/27

Quite a while ago, a co-worker asked how to get tot the Instance variable when using a with statement like this:

function TMyForm.ExecuteForm(FormClass: TFormClass): Integer;
begin
  with FormClass.Create(self) do
    try
      Result := ShowModal;
    finally
      Free;
    end;
end;

So I wrote the blog entry below when I started my blog last week, and set the published date to somewhere early May, a week that will be really busy.
Then I found out about the Stackoverflow question Reference object instance created using “with” in Delphi followed by the answer by user ‘Alexander‘ (a really smart Russian guy).
Enough coincidence to publish the blog article earlier than scheduled :-) 

Before I explain why I really hate ‘with’, lets show what my co-worker wanted, and my solution:

uses
  ObjectHelperUnit;
// ...
function TMyForm.ExecuteForm(FormClass: TFormClass): Integer;
begin
  with FormClass.Create(self) do
    try
      // just an example on how you could use Instance:
      TForm(Instance).Caption := Instance.ClassName;
      Result := ShowModal;
    finally
      Free;
    end;
end;

First, let me show a few examples why ‘with’ is bad:

  • the debugger cannot peek through with, so you will see different results in the debugger than the code that actually executes. See the question on Debugging problems with ‘WITH’ statement in Delphi 2006 at Stackoverflow or this code:
    procedure TMyForm.ButtonClick(Sender: TObject);
    begin
      with MyLabel do
      begin
        // note: debugger sees the Caption of the Form, but user the Caption of MyLabel!
        ShowMessage(Caption);
      end;
    end;
    
  • it bites you when doing code like this:
    procedure TMyForm.ButtonClick(Sender: TObject);
    begin
      with MyEdit do
      begin
        // note: MyEdit does not have a Caption!
        Caption := Sender.ClassName;
      end;
    end;
    

So better not use the class helper, but a local variable:

function TMyForm.ExecuteForm(FormClass: TFormClass): Integer;
var
  ModalForm: TFormClass;
begin
  ModalForm := FormClass.Create(Self);
  try
    ModalForm.Caption := ModalForm.ClassName;
    Result := ModalForm.ShowModal;
  finally
    ModalForm.Free;
  end;
end;

Back to getting the instance, this too can be solved with class helpers (a special compiler feature that was introduced quite a few Delphi versions ago for .NET portability reasons and since Delphi 2005 has been backported to the Win32 version of the compiler).

The nifty class helper below will get you going doing your bizarre “with circumvention”.
Edit @ 20090429: Stackoverflow user Vegar correctly noted that this will effectively kill any other class helpers for TObject or its descendants. Yet another reason not to use with :-)

So, before you read further, read this disclaimer:
Try to avoid with. With stunts are performed by professionals. Please do not try them at home, work or any other place.”

–jeroen

unit ObjectHelperUnit;

interface

type
  TObjectHelper = class helper for TObject
  public
    function Instance: TObject; // trick to circumvent the 'with' statement
  end;

implementation

{ TObjectHelper }

function TObjectHelper.Instance: TObject;
begin
  Result := Self;
end;

end.

2 Responses to “Delphi – bizarre use of class helpers to circumvent ‘with’”

  1. […] I wrote before, I’m with the Delphi with haters camp, and this is […]

  2. […] The Wiert Corner: class helper to circumvent ‘with’ […]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

 
%d bloggers like this: