По факту:
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
может быть просто регистром ЦП, но также может быть настоящей временной переменной в стеке. Конечно, здесь я использую указатели, поскольку TRect
- это record
. Это более прямолинейно для объектов, поскольку они уже являются указателями.
Лично я иногда использовал with в своем коде, но я почти каждый раз проверяю сгенерированный asm, чтобы убедиться, что он делает то, что должен. Не все могут или имеют время сделать это, поэтому, IMHO, локальная переменная - хорошая альтернатива with.
Мне очень не нравится такой код:
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
, чтобы получить внутренние значения.
person
Arnaud Bouchez
schedule
04.09.2012