Gar*_*cks 6 delphi with-statement
我正在尝试正确使用delphi中的语句.
总的来说,做简单的事情似乎相当简单,但我有兴趣找到一些关于使用嵌套语句的好的代码示例和/或教程.例如
with object1, object2, etc... do
begin
statements
end;
Run Code Online (Sandbox Code Playgroud)
我不确定的是以这种方式使用语句时的优先顺序.
任何建议表示赞赏.
Nic*_*ges 20
我能给你的最好建议是:
不要永远使用.
如果你想使用'with',那就去躺下,直到感觉过去.
如果你想使用嵌套,用锤子敲击你的手直到欲望消失.
'with'只是一个等待发生的错误.更改使用它的类可以改变代码的含义.它创建了不精确的语义,这总是很糟糕.
保存击键绝不是使用'with'的好理由.现在再进行一些击键可以为您节省很多痛苦.
'应该'应该避开.
在线参考的摘录指出:
当with之后出现多个对象或记录时,整个语句被视为一系列嵌套的语句.从而:
Run Code Online (Sandbox Code Playgroud)with obj1, obj2, ..., objn do statement相当于:
Run Code Online (Sandbox Code Playgroud)with obj1 do with obj2 do ... with objn do // statement在这种情况下,如果可能,语句中的每个变量引用或方法名称都将被解释为
objn; 否则,如果可能,将其解释为objn1; 等等.该规则同样适用于解释OBJ文件本身,所以,举例来说,如果objn是两者的成员obj1和obj2,它被解释为obj2.objn.
既然有足够的意见,我会尽力回答你的问题,虽然这个前面的答案很好地回答了你问题的语法部分.它对文档的引用解释了优先顺序,以及其他有趣的规则.将其视为强制性阅读.
正如您可能已经理解的那样,(一个未经证实的)唯一的问题with是,您可以Self使用相同的名称来寻址(或者来自一个嵌套级别的实例)的成员,而不是寻址特定的实例成员.显然不打算:
procedure TForm1.SomeRoutine;
var
Button: TControl;
begin
Button := Button1;
with Button do
Caption := 'Press here';
end;
Run Code Online (Sandbox Code Playgroud)
运行,并惊讶于表单的标题已更改.当然,TControl声明一个Caption属性,但是那个属性是受保护的,因此Caption在此代码中引用了该形式的属性.但是下一个示例也不保证设置按钮的标题:
procedure TForm1.SomeRoutine;
begin
with Button1 do
Caption := 'Press here';
end;
Run Code Online (Sandbox Code Playgroud)
......因为也许Button1被声明为其中一些异国情调的按钮类型有一个标题,但物业的名称可能是Title,Beschriftung或Legende.
这些是简单的例子,很容易修复,几乎不需要调试.但是考虑内存中记录和对象的非可视成员:这些错误很难调试,因为:在哪里看?当然,运气不错,Self没有这样的成员,以防编译器发出警告:
procedure TForm1.SomeRoutine;
begin
with Button1 do
Cpation := 'Press here';
end;
Run Code Online (Sandbox Code Playgroud)
...但不要指望只会产生编译器捕获的错误.
这种错误很容易实现.由我,由您和任何其他(经验丰富的)开发人员.特别是当您处理或使用正在构建或正在重构的代码时.很明显,对于嵌套的withs,这些错误的调试问题正在堆积成指数级别.
现在,与我们这里的其他人不同,我with经常使用,但仅限于固定库类型,其成员永远不会被重命名.例如:TRect, TPoint, TMessage, TGridRect, TControl, TCanvas,etc ...就是几乎所有的RTL记录类型以及一些VCL类,但几乎从不在我自己的库类型上.如果你真的不想使用with,我建议如下:
安全的例子:
with ARect do
ExcludeClipRect(DC, Left, Top, Right, Bottom); //TRect will always have these
Run Code Online (Sandbox Code Playgroud)棘手的例子:
with Query, Parameters do
begin
Connection := AConnection;
ParamValues['ID'] := ID; //TParameters has a few same named members as dataset
Open;
end;
Run Code Online (Sandbox Code Playgroud)不好的例子:
with TMyLabel do
Color := clYellow; //My label may become transparent in future
Run Code Online (Sandbox Code Playgroud)我已成为无营地的成员.
我上面的例子假设with只有向上的危险,比如混合Child.Caption和Self.Caption.但是最近,当将一些代码从D7移植到XE2时,我在向下方向遇到了麻烦.实际上,使用上面的"安全示例",当然:
with GripRect[I] do
begin
...
Left := Width - W[I];
Run Code Online (Sandbox Code Playgroud)
打算Width成为Self,但由于XE2 TRect也有Width成员,我不得不重写代码:
Left := Self.Width - W[I];
Run Code Online (Sandbox Code Playgroud)
结论:确实没有安全的用法with.