В самом деле:
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
непосредственно, чтобы получить внутренние значения.
Это звучит как проблема с отладчиком, а не проблема с языковой функцией. – 2008-09-16 11:40:12
@GregHewgill Вы правы, это проблема с отладчиком. Но это по-прежнему совершенно разумная причина, чтобы избежать его использования. Кроме того, это не оправдывает все проблемы с языковыми функциями ** с помощью **. Самое большое существо, которое ** с ** фактически ** _ уменьшает читаемость **. ПРИМЕЧАНИЕ. Меньший код (с использованием ** с **) не улучшает читаемость автоматически. Он уменьшает его, потому что он больше не является явным, о чем идет речь в области идентификаторов внутри блока ** с **. Объявление и инициализация локального псевдонима переменной приводит к аналогичному сокращению кода, но поддерживает явное разыменование. – 2012-06-07 07:51:09