На самом деле:
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
. Он более прямой для объектов, поскольку они уже являются указателями.
Лично я использовал иногда с моим кодом, но я почти каждый раз проверяю сгенерированный 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
, чтобы получить внутренние значения.