Skip to main content
Thoughts from David Cornelius

Category

As a Delphi MVP, I was surveyed on my stance of the use of FreeAndNil. In that questionnaire was included a question about the use of Assigned(). Really? Is that debated as well? I couldn't find anything on the internet debating this except for an old discussion on StackOverflow. I use this function frequently and as I looked more deeply at what it does, I'm even more confident of its use.

Basically what the System.Assigned() function does is "Tests for a nil (unassigned) pointer or procedural variable." In other words, the following statement makes sure the variable P is not nil:

if Assigned(P) then ...

On the surface, that seems equivalent to just simply writing:

if P <> nil then ...

For regular object variables, that is equivalent but this function also works on procedural variables. If P is a procedural variable, you'd have to write this instead:

if @P <> nil then ...

By using Assigned(), both of those scenarios are automatically covered.

My most frequent use of Assigned is when calling event handlers from a class. For example, let's say I have a class that performs a task and it provides events for when it starts, stops, and to report its progress. The calling program or class can hook into those events to log the activity or display status on the screen to the user. It might look like this:

type 
  TMyTaskClass = class
  private
    FOnStartTask: TNotifyEvent;
    FOnEndTask: TNotifyEvent;
    FOnNotifyProgress: TGetStrProc;
  public
    property OnNotifyProgress: TGetStrProc read FOnNotifyProgress write FOnNotifyProgress;
    property OnStartTask: TNotifyEvent read FOnStartTask write FOnStartTask;
    property OnEndTask: TNotifyEvent read FOnEndTask write FOnEndTask;
  end;

The class would have additional methods to do the work for which this class was designed and somewhere in those methods the event handlers would need to be called. But hooking into the events is optional--this class could be used, for example, from a unit test that completely ignores the events. So each time the event handlers are called, they need to be checked to see if they're assigned. Doing that every time you need to call an event is messy so I put those checks into "Do" methods, typically in a "protected" section of the class:

protected 
  procedure DoOnNotifyProgress(const S: string);
  procedure DoOnStartTask(Sender: TObject);
  procedure DoOnEndTask(Sender: TObject);

The bodies of these procedures look like this:

procedure TMyClass.DoOnNotifyProgress(const S: string);
begin
  if Assigned(FOnNotifyProgress) then
    FOnNotifyProgress('Progress: ' + S);
end;

procedure TMyClass.DoOnEndTask(Sender: TObject);
begin
  if Assigned(FOnEndTask) then
    FOnEndTask(Self);
end;

procedure TMyClass.DoOnStartTask(Sender: TObject);
begin
  if Assigned(FOnStartTask) then
    FOnStartTask(Self);
end;

The call to Assigned() in these procedures checks to see if the event handlers are hooked up and if so, calls them. The main body of the class can now simply call these "Do" procedures whenever it needs to trigger event handlers.

Another common use is when parsing XML or JSON data. For example, the System.JSON.TJSONValue.GetValue function returns an object parsed from a JSON string but if the Path parameter was not found, the result is nil. Checking for this is key when dealing with public REST APIs that may return varying results.

Other places where I use the Assigned() test is in the destructor of a class that created objects in the constructor and I want to make sure they were actually created before attempting to free their memory. (Of course, if you adhere to Dependency Injection principles, strongly promoted by Nick Hodges, your classes won't typically create their own objects--a practice I should adopt more rigidly.)

An aesthetic advantage to using Assigned() over explicitly checking the value against nil is if there are multiple clauses in an if statement, you don't need to use as many parenthesis--a minor point but keeps the code just a little cleaner and easier to read.

One important thing to remember is that Assigned() does not validate a pointer, it simply checks to see if the pointer has some value indicating it was purposefully assigned at some point with a valid address; the object to which it points could've been freed--an argument for promoting the use of FreeAndNil.

Overall, I believe that Assigned() is very useful in many cases--I doubt many will disagree.

Add new comment

The content of this field is kept private and will not be shown publicly.
CAPTCHA
Please enter the characters shown; no spaces but it is case-sensitive.
Image CAPTCHA
Enter the characters shown in the image.