实际上:
procedure TBitmap32.FillRectS(const ARect: TRect; Value: TColor32);
begin
with ARect do FillRectS(Left, Top, Right, Bottom, Value);
end;
和
procedure TBitmap32.FillRectS(const ARect: TRect; Value: TColor32);
begin
FillRectS(ARect.Left, ARect.Top, ARect.Right, ARect.Bottom, Value);
end;
将生成完全相同的汇编代码。
with
如果子句的值是函数或方法,则可能存在性能损失。在这种情况下,如果您想要良好的维护和良好的速度,只需执行编译器在后台执行的操作,即创建一个临时变量。
实际上:
with MyRect do
begin
Left := 0;
Right := 0;
end;
由编译器以伪代码编码:
var aRect: ^TRect;
aRect := @MyRect;
aRect^.Left := 0;
aRect^.Right := 0;
然后aRect
可以只是一个 CPU 寄存器,但也可以是堆栈上真正的临时变量。当然,我在这里使用指针,因为TRect
它是record
. 它对对象更直接,因为它们已经是指针。
就个人而言,我有时在我的代码中使用 with,但我几乎每次生成 asm 时都会检查以确保它完成了它应该做的事情。不是每个人都能或有时间去做,所以恕我直言,局部变量是一个很好的替代方案。
我真的不喜欢这样的代码:
for i := 0 to ObjList.Count-1 do
for j := 0 to ObjList[i].NestedList.Count-1 do
begin
ObjList[i].NestedList[j].Member := 'Toto';
ObjList[i].NestedList[j].Count := 10;
end;
它仍然很容易阅读:
for i := 0 to ObjList.Count-1 do
for j := 0 to ObjList[i].NestedList.Count-1 do
with ObjList[i].NestedList[j] do
begin
Member := 'Toto';
Count := 10;
end;
甚至
for i := 0 to ObjList.Count-1 do
with ObjList[i] do
for j := 0 to NestedList.Count-1 do
with NestedList[j] do
begin
Member := 'Toto';
Count := 10;
end;
但如果内部循环很大,则局部变量确实有意义:
for i := 0 to ObjList.Count-1 do
begin
Obj := ObjList[i];
for j := 0 to Obj.NestedList.Count-1 do
begin
Nested := Obj.NestedList[j];
Nested.Member := 'Toto';
Nested.Count := 10;
end;
end;
这段代码不会比以下代码慢with
:编译器实际上是在幕后完成的!
顺便说一句,这将使调试更容易:您可以放置一个断点,然后将鼠标指向Obj
或Nested
直接获取内部值。