Search code examples
delphidelphi-7

Delphi - how to check method variable?


In Delphi (I'm using D7), how do I check that a method variable is assigned to something? I've tried this code

function MethodIsOK(M : TMethod) : Boolean;
begin
  //Result := M <> Nil;
  //Result := Assigned(M);
end;

but either way of assigning Result gives an `Incompatible types' compilation error


Solution

  • When a TMethod-based method pointer is passed to the intrinsic Assigned() function, it returns whether the TMethod.Code field is non-nil, regardless of the TMethod.Data field (you can call an object method on an invalid object pointer), eg:

    function MethodIsOK(M : TMethod) : Boolean;
    begin
      //Result := Assigned(M);
      Result := M.Code <> nil;
    end;
    

    Allen Bauer blogged about this very issue and why Assigned() was introduced for method pointers to support design-time code:

    Assigned or not Assigned, that is the question…

    The implementation of a method pointer for native code (Win16 and Win32, and the upcomming Win64 implementation), consists of two pointers. One points to the address of the method and the other to an object instance. It turns out that the simple if methodpointer <> nil then statement would check that both pointers were nil, which seems logical, right? And it is. However, there is a bit of a hitch here. At design-time, the native VCL form designer pulls a few tricks out of its hat. We needed a way to somehow assign a value to a component’s method pointer instance, but also make sure the component didn’t actually think anything was assigned to it and promptly try and call the method (BOOM!!). Enter, Assigned. By adding the standard function, Assigned, we could preserve the <> nil sematics, and also introduce a twist. It turns out, and for the adventurous among you can verify this, that Assigned only checks one of the two pointers in a method pointer. The other pointer is never tested. So what happens is that when you "assign" a method to the method pointer from within the IDE’s Object Inspector, the designer is actually jamming an internally created index into the other (non-Assigned-tested) pointer within the method pointer structure. So as long as your component uses if Assigned(methodpointer) then before calling through the method pointer, your component code will never misbehave at design-time.