为什么当 btn 为 NIL 时我可以访问 btn.Caption?
Why I can access btn.Caption when btn is NIL?
为什么这段代码不会崩溃? T
为零。如果 T
是 nil
,如何访问 Caption
?
procedure Crash;
VAR T: TButton;
begin
T:= NIL;
T.Caption:= ''; <---------- this works
end;
TButton
控件是 Win32 Button 控件的包装器。它使用 Windows 消息系统对其进行操作。如果 Self
是 nil
:
,这样做的核心方法 TControl.Perform()
具有防止发送消息的内置保护措施
function TControl.Perform(Msg: Cardinal; WParam: WPARAM; LParam: LPARAM): LRESULT;
var
Message: TMessage;
begin
Message.Msg := Msg;
Message.WParam := WParam;
Message.LParam := LParam;
Message.Result := 0;
if Self <> nil then // <-- here
WindowProc(Message);
Result := Message.Result;
end;
Caption
是一个 属性,其 setter 使用非虚拟 TControl.GetText()
和 TControl.SetText()
方法,可以安全地调用 nil
对象,因为它们的功能依赖于向控件发送各种消息(WM_GETTEXTLEN
和 WM_SETTEXT
),并且只涉及局部变量或传递的参数。所以在 nil
时不会访问实际对象,因此不会崩溃。
为什么这段代码不会崩溃? T
为零。如果 T
是 nil
,如何访问 Caption
?
procedure Crash;
VAR T: TButton;
begin
T:= NIL;
T.Caption:= ''; <---------- this works
end;
TButton
控件是 Win32 Button 控件的包装器。它使用 Windows 消息系统对其进行操作。如果 Self
是 nil
:
TControl.Perform()
具有防止发送消息的内置保护措施
function TControl.Perform(Msg: Cardinal; WParam: WPARAM; LParam: LPARAM): LRESULT;
var
Message: TMessage;
begin
Message.Msg := Msg;
Message.WParam := WParam;
Message.LParam := LParam;
Message.Result := 0;
if Self <> nil then // <-- here
WindowProc(Message);
Result := Message.Result;
end;
Caption
是一个 属性,其 setter 使用非虚拟 TControl.GetText()
和 TControl.SetText()
方法,可以安全地调用 nil
对象,因为它们的功能依赖于向控件发送各种消息(WM_GETTEXTLEN
和 WM_SETTEXT
),并且只涉及局部变量或传递的参数。所以在 nil
时不会访问实际对象,因此不会崩溃。