Fun Code of the Day #2: Does nil have a type?

Okay, no cheating now. That is, no running the code until you’ve guessed.

What is the output of this code?

program Project90;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils;

  var
    S: TObject;

begin
  try
    S := nil;
    if S is TObject then
    begin
      Writeln('Yup');
    end else
    begin
      Writeln('Nope');
    end;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;
end.

How sure are you?

Now run it and find out. Were you right?

8 Replies to “Fun Code of the Day #2: Does nil have a type?”

  1. Well, I wasn’t right. I tought that an exception would be raised. Nil aka null always introduced the “third possible state” ambiguity. I’m not actually sure what should actually happen. Hated nil since the beggining, it brings in so much FUD

  2. I guessed right: the is operator always returns False with nil.

    Wanna really break your brain, though? Add a second variable, T: TObject. Add in a line after the assignment:

    T := S as TObject;

    What is the resulting behavior?

    • I haven’t had time to try this yet – what is the behaviour? I’m going to guess something odd 🙂

  3. I would have to say “Nope”. Because once you set an Object to “nil” it becomes… well… nil. It “IS” no longer an Object… it is Nothing… however, it wouldn’t throw an exception, because the the variable is still declared, it is just set to nothing. “IS”, is the key here. Because you’re doing a test to see what the object is. Like checking for a “Sender” in a command click. You can call a command button click from anywhere in your code… however, if you do a test to see if the Sender “IS” a TButton object, the code inside the TButton block will not run.

    See my screen shot below:

  4. This must be a special path in the compiler but it surprised me because it didn’t dereference a nil somewhere internally and cause an AV. I expected an access violation, as I didn’t believe that it was safe to check nil is. In fact, as other commenters stated, some other non-TObject types are NOT safe to use “is X” unless you know it’s not null.

    In code review I would always insist on “if Assigned(x) and (x is TSomething)” because of these crashes.

    W

  5. It’s interesting topic 🙂 and I experimented little bit more. Actually when type of variable and IS class are the same – generated code for is operator is always just check for nil – if it’s not nil then compiler suppose it’s instance of given class, doesnt check actually with IsClass or for valid pointer and thats why it doesnt raise AV. Actually generated code for “if S is TSimpleRWSync” and “if Assigned(S)” is exactly the same – just check for nil. The optimization is not special for TObject, but for any class.

  6. I was correct that it would not be an access violation and that ‘NOPE’ would be displayed. So S is still a variable but just contains nothing. If you comment out S:=NIL; you will see NOPE again because it exists but does not contain anything to reference.

Comments are closed.