Delphi:尽量避免使用'with'语句
在 Delphi 中使用 with 语句会使您的代码不那么面向未来。
最初,Pascal 中的语句在一定程度上是允许编译器优化的:
with
PASCAL 用户手册和报告 – Kathleen Jensen、Niklaus Wirth – Google 图书
with 子句有效地打开了包含指定记录变量的字段标识符的作用域,以便字段标识符可以作为变量标识符出现。(从而为编译器提供了优化限定语句的机会。)
这本 1975 年的书的屏幕截图如下。
Delphi(实际上甚至在 Turbo Pascal 编译器之前)在代码和非代码之间没有可衡量的区别。
with
with
但是,调试器仍然不支持,并且还有其他缺点,如下所示。
下面的代码示例只是众多代码示例之一。我之所以展示它,是因为我最近碰到了一些早就应该移植到 Delphi XE3 的代码。
由于我以前被咬过几次,所以没过多久我就找到了原因。with
示例代码 where 的类型是用于编译精细:FIConData
NOTIFYICONDATAW
1 2 3 4 5 6 7 8 9 10 | with FIconData do begin cbSize := SizeOf(FIconData); Wnd := Self . Handle; uID := $DEDB ; uFlags := NIF_MESSAGE or NIF_ICON or NIF_TIP; hIcon := Application . Icon . Handle; uCallbackMessage := WM_CAS400NTIcon; StrCopy(szTip, PChar (Caption)); end ; |
好吧,从编译器版本 20 开始,它不再编译了。
原因是_NOTIFYICONDATAW已更改,因为基础 Windows API NOTIFYICONDATA 结构已更改以适应新的 Windows Vista 功能。
但是,由于向后兼容性,在 Windows Vista 之前的 Windows 版本上运行时,无法传递完整的新结构。
因此,这段代码用于计算截至 Delphi 2009 的单元中的正确结构大小:ShellApi
1 2 3 4 5 6 7 8 9 | class function _NOTIFYICONDATAW . SizeOf: Integer ; static; begin if Win32MajorVersion >= 6 then // Size of complete structure Result := System . SizeOf(_NOTIFYICONDATAW) else // Platforms prior to Vista do not recognize the fields guidItem and hBalloonIcon Result := System . SizeOf(_NOTIFYICONDATAW) - System . SizeOf(TGUID) - System . SizeOf(Winapi . Windows . HICON); end ; |
SizeOf
这是一个非常好的名字,但当你使用这个语句时,它会发生冲突。with
添加了其他三个功能。这是四个的完整列表:SizeOf
- 单元窗口:
- 类函数 tagNONCLIENTMETRICSA.SizeOf: Integer;
- 类函数 tagNONCLIENTMETRICSW.SizeOf: Integer;
- 单位通讯:
- 类函数 MCHITTESTINFO。SizeOf:整数;
- 单位 ShellApi:
- 类函数_NOTIFYICONDATAW。SizeOf:整数;静态的;
你很想重写这样的内容:with
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | with FIconData do begin {$if CompilerVersion >= 20} cbSize := SizeOf(); { $else } cbSize := SizeOf(FIconData); {$ifend CompilerVersion >= 20} Wnd := Self . Handle; uID := $DEDB ; uFlags := NIF_MESSAGE or NIF_ICON or NIF_TIP; hIcon := Application . Icon . Handle; uCallbackMessage := WM_CAS400NTIcon; StrCopy(szTip, PChar (Caption)); end ; |
但实际上你应该像这样重写它,这样你就可以确定每个值来自哪个实体:
1 2 3 4 5 6 7 8 9 10 11 | {$if CompilerVersion >= 20} FIconData . cbSize := FIconData . SizeOf(); { $else } FIconData . cbSize := SizeOf(FIconData); {$ifend CompilerVersion >= 20} FIconData . Wnd := Self . Handle; FIconData . uID := $DEDB ; FIconData . uFlags := NIF_MESSAGE or NIF_ICON or NIF_TIP; FIconData . hIcon := Application . Icon . Handle; FIconData . uCallbackMessage := WM_CAS400NTIcon; StrCopy(FIconData . szTip, PChar (Caption)); |