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,445 other followers

TObjectHelper for easier debugging a cast mismatch and a typed FreeAndNil

Posted by jpluimers on 2018/10/10

The below came in really useful in an old project I took over that was full of bugs having to do with improper casts and FreeAndNil usage.

EDIT 20181010: WordPress.com keeps mangling angle-brackets in pre and code sections, so I added the code to a gist; see link below.

First the examples.

procedure TMyServer.UnbindFromIdTcpServerStatusContext(const aContext: TIdContext);
var
  lClientSession: TClientSession;
begin
  lClientSession := TObjectHelper.Cast<TClientSession>(aContext.Data);
...
end;

type
  TBaseDataInterface = class(TObject)
  strict private
    FDatabase:      TIBDatabase;
    FTransaction:   TIBTransaction;
...
  end;


destructor TBaseDataInterface.Destroy();
begin
  TObjectHelper.FreeAndNil(FDatabase);
  TObjectHelper.FreeAndNil(FTransaction);
...
  inherited Destroy();
end;

And the implementation.

unit ObjectHelperUnit;

interface

type
  TObjectHelper = record
    class function Cast<T: class>(const aValue: TObject): T; static;
    class procedure FreeAndNil<T: class>(var Value: T); static;
  end;

implementation

uses
  System.SysConst,
  System.SysUtils;

class function TObjectHelper.Cast<T>(const aValue: TObject): T;
var
  lException: Exception;
begin
  if Assigned(aValue) then
  begin
    if aValue is T then
      Result := T(aValue)
    else
    begin
      lException := EInvalidCast.CreateFmt('%s; actual type %s but expected %s.',
        [SInvalidCast, aValue.QualifiedClassName, T.QualifiedClassName]);
      raise lException;
    end;
  end
  else
    Result := nil;
end;

class procedure TObjectHelper.FreeAndNil<T>(var Value: T);
begin
  System.SysUtils.FreeAndNil(Value);
end;

end.

–jeroen

Gist:

16 Responses to “TObjectHelper for easier debugging a cast mismatch and a typed FreeAndNil”

  1. HeartWare said

    I use this:

    TYPE
    TObjectHelper = CLASS HELPER FOR TObject
    FUNCTION CastAs<T:CLASS&gt : T;
    FUNCTION IsClass(T : TClass) : BOOLEAN;
    END;

    FUNCTION TObjectHelper.CastAs<T> : T;
    BEGIN
    IF IsClass(T) THEN Result:=T(Self) ELSE Result:=NIL
    END;

    FUNCTION TObjectHelper.IsClass(T : TClass) : BOOLEAN;
    BEGIN
    IF NOT Assigned(Self) THEN
    Result:=FALSE
    ELSE IF NativeInt(Self)<$10000 THEN
    Result:=FALSE
    ELSE TRY
    Result:=Self IS T
    EXCEPT
    Result:=FALSE
    END
    END;

    as in

    VAR O : TObject;
    VAR C : TControl;
    C:=O.CastAs<TControl>;

    C is then either NIL or a properly cast TControl. A bit like C#’s “as” operator.

    • HeartWare said

      How do you format the source code to keep indentation etc.?

    • jpluimers said

      You are right that the C# casts as and () are different than in Delphi: in C#, the as returns null when it fails; the () throws an exception. In Delphi, the as throws an exception, and () breaks in mysterious ways when the cast does not match.

      I wanted to stay close to the Delphi way, but have a more clear error message.

  2. Jacek said

    This will not compile, no generic declaration of type T.
    Or I do not know something :-)

  3. Gloegg said

    I think the source is missing a either in the class or on the methods.
    For the Cast method it should even be

    • jpluimers said

      It is WordPress. It often messes with angle brackets in code and pre blocks. Fixed by now. Hopefully it stays fixed when I save it.

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

 
%d bloggers like this: