Является Delphi “с” ключевым словом плохой практикой?

.L3:
    movslq  %esi, %rdx           /* sign extend counter<%esi> to 64bit %rdx */
    addl    (%rdi,%rdx,4), %eax  /* res<%eax> += b<%rdi>[counter<%rdx>]; */
    subl    $1, %esi             /* counter<%esi> -= 1              */
.L2:
    testl   %esi, %esi           /* do counter<%esi> & counter<%esi> */
    jns     .L3                  /* if result is no 0, jump to L3  */

В основном addl (%rdi,%rdx,4), %eax - это доступ к массиву (%rdi) с индексом счетчика (%rdx) и добавление значения элемента в res (%eax), 4 это просто умножение счетчика (%rdx) для доступа к памяти, поскольку каждый адрес в массиве int потребляет 4 байта в памяти вашей системы.

Строка в основном говорит: res += MEMORY[addrssOf(b) + counter*4]

Кстати, я думаю, вы хотите проверить, что size > 0 перед строкой int counter = size-1;, а также, как P__J__ упоминается в его ответе, ваш res может переполнение, поскольку оно имеет одинаковый тип каждого элемента в массиве, который вы суммируете.

34
задан Lars Truijens 17 January 2012 в 08:42
поделиться

11 ответов

Самая большая опасность с, за пределами патологических состояний как "с A, B, C, D" состоит в том, что Ваш код может тихо изменить значение без уведомления Вам. Рассмотрите этот пример:

with TFoo.Create
try
  Bar := Baz;
  DoSomething();
finally
  Free;
end;

Вы пишете этот код, зная, что Панель является свойством TFoo, и Baz является свойством типа, содержащего метод, который имеет этот код.

Теперь, два года спустя, некоторый действующий из лучших побуждений разработчик входит, добавляет свойство Baz к TFoo. Ваш код тихо изменил значение. Компилятор не будет жаловаться, но код теперь взломан.

58
ответ дан Craig Stuntz 27 November 2019 в 15:51
поделиться

с [1 115] ключевое слово является хорошей функцией того, чтобы сделать Ваш код более читаемым, но существуют некоторые ловушки.

Отладка:

При использовании кода как это:

with TMyClass.Create do
try
  Add('foo');
finally
  Free;
end;

нет никакого способа осмотреть свойства этого класса, поэтому всегда объявлять переменную и использовать с [1 117] ключевое слово на этом.

Интерфейсы:

При создании интерфейса в с [1 119] пункт это живет до конца метода:

procedure MemoryHog;
begin
  with GetInterfaceThatTakes50MBOfMemory do
    Whatever;
  ShowMessage('I''m still using 50MB of memory!');
end;

Ясность

При использовании класса в с [1 121] пункт, который имеет свойства или имена методов, который уже существует в объеме, он может одурачить Вас легко.

with TMyForm.Create do
  Width := Width + 2; //which width in this with is width?

, Конечно, при наличии двойных названий, Вы используете свойства и методы класса, объявленного в Вашем с оператором (TMyForm).

31
ответ дан The_Fox 27 November 2019 в 15:51
поделиться

with оператор имеет свое место, но я должен согласиться, что злоупотребление может привести к неоднозначному коду. Хорошее эмпирическое правило состоит в том, чтобы удостовериться, что код более читаем и удобен в сопровождении после добавления с оператором. Если Вы чувствуете, что необходимо добавить комментарии для объяснения кода после добавления оператора затем, это - вероятно, плохая идея. Если код более читаем, поскольку в Вашем примере затем используют его.

btw: это всегда было одним из моих любимых шаблонов в Delphi для показа модального окна

with TForm.Create(nil) do
try
  ShowModal;
finally
  Free;
end
22
ответ дан David Heffernan 27 November 2019 в 15:51
поделиться

Я склоняюсь к отравлению с оператором в целом. Как ранее указано, это может сделать вещи сложными, и мой опыт состоит в том, что это будет. Много раз отладчик хочет, оценивают значения из-за withs, и все часто я нахожу вложенные withs, которые ведут для кодирования этого трудно для чтения.

код Brian кажется читаемым и хорошим, но код был бы короче, если Вы просто преобразовываете тип отправителя непосредственно, и Вы удаляете все сомнение относительно того компонента, который Вы включаете:

TAction(Sender).Enabled := Something;

, Если Вы обеспокоены вводом к очень, я предварительно тарифицирую для создания временной ссылки на длинный именованный объект:

var
  t: TTable;
begin
  t := theLongNamedDataModule.WithItsLongNamedTable;
  t.FieldByName(' ');
end;

я не могу se, почему ввод должен побеспокоить Вас, все же. Мы - Машинистки Сначала, Программисты, Вторые , и завершение кода, вставка копии и запись ключа могут помочь Вам быть более эффективной машинисткой.

обновление: Просто споткнувшийся длинная статья с небольшим разделом по с операторами: он с ключевым словом. Самое отвратительное, опасное, blow-your-own-feet-off функция на языке. :-)

15
ответ дан Craig Stuntz 27 November 2019 в 15:51
поделиться

Когда я сначала начал программирование Паскаля (с TurboPascal!) и изученный, когда я пошел С замечательным казавшимся. Как Вы говорите, ответ на утомительный ввод и идеал для тех длинных записей. Так как Delphi прибыл, я удалял его и поощрял другой отбрасывать его - аккуратно суммированный Verity в регистр Кроме сокращения удобочитаемости существует две главных причины, почему я избежал бы его:

  1. при использовании класса затем, Вам не нужен он так или иначе - только записывает, 'кажется', извлекают выгоду из него.
  2. Используя отладчик для следования коду к объявлению с Ctrl-Enter не работает.

Тем не менее для удобочитаемости я все еще использую синтаксис:

procedure ActionOnUpdate( Sender : TObject )
begin
  With Sender as TAction do
    Enabled := Something
end;

я не видел лучшую конструкцию.

8
ответ дан Brian Frost 27 November 2019 в 15:51
поделиться

Вашим примером, datamodule доступа в рамках нажатия кнопки, является плохо изобретенный пример, по-моему. Целая потребность в С уходит при перемещении этого кода в модуль данных, где это должно быть. OnClick затем просто называет LongNameDataModule. InsertStuff и существует не с необходимым.

С плохое устройство, и необходимо посмотреть код для наблюдения, почему Вам нужен он. Вы, вероятно, сделали что-то не так или могли сделать это лучший путь.

6
ответ дан mj2008 27 November 2019 в 15:51
поделиться

Я - твердый сторонник удаления С поддержкой в Delphi. Ваше использование в качестве примера использования datamodule с именованными полями о единственном экземпляре, который я видел, что он разработал. Иначе лучший аргумент против него был дан Craig Stuntz - который я проголосовал.

я точно так же, как, чтобы указать, что со временем Вы можете в конечном счете (должен) rmeove, который все кодирование в событиях OnClick и Вашем коде также в конечном счете переместит далеко от именованных полей на datamodules в использование классов, которые переносят эти данные, и причина использовать С уйдет.

5
ответ дан Darian Miller 27 November 2019 в 15:51
поделиться

Основная проблема с "с" состоит в том, что Вы не знаете, где ее объем заканчивается, и у Вас могли быть несколько накладывающиеся с операторами.

я не думаю, что необходимо избегать использования его, пока код читаем.

Одно из предложений сделать это более читаемый (и менее сбивающий с толку в более длинном коде) было, если codegear добавил опция допускать псевдонимы в с, и вероятно позволяющий несколько withs в одном:

procedure TMyForm.AddButtonClick(Sender: TObject);
begin  
  with LongNameDataModule as dm, dm.LongNameTable1 as t1, dm.LongNameTable2 as t2 do
  begin
    t1.Insert;
    t1.FieldByName('Field1').AsString := 'some value';
    t1.FieldByName('Field2').AsString := t2.FieldByName('Field2').AsString;
    t1.Post;
    dm.Connection.Commit;
  end
end;
3
ответ дан Osama Al-Maadeed 27 November 2019 в 15:51
поделиться

Что касается меня, С довольно приемлемо в случае, который Вы даете. Это, конечно, улучшает ясность кода.

реальное зло - когда у Вас есть несколько with's, открытый сразу.

кроме того, мое мнение - то, что то, с чем Вы используете на, имеет большое значение. Если это - действительно другой объект затем с, вероятно, плохая идея. Однако мне не нравится иметь много переменных на одном уровне, даже когда это имеет смысл - обычно объекты данных, которые содержат весь очень сложный элемент данных - обычно вся обрабатываемая деталь, с которой программа разработана для работы. (Я не думаю, что этот случай произошел бы в приложении, которое не имело такого объекта.) Для создания мира более ясным, я часто использую записи на связанные с группой объекты. Я нахожу, что почти все withs, которые я использую, для доступа к таким подгруппам.

3
ответ дан Loren Pechtel 27 November 2019 в 15:51
поделиться

Существует много превосходных ответов здесь относительно того, почему с оператором плохо, таким образом, я попытаюсь не повторить их. Я использовал с оператором в течение многих лет, и я очень начинаю уклоняться от него. Это частично beause, может быть трудно разработать объем, но я начинал входить в рефакторинг в последнее время, и ни один из автоматизированных рефакторингов не работает скручивание жгутов с оператором - и автоматизировал рефакторинг, является потрясающим.

Также некоторое время назад я сделал видео на том, почему с оператором плохо, это не одна из моих лучших работ, но Здесь это

2
ответ дан Alister 27 November 2019 в 15:51
поделиться

Ваш вопрос является отличным примером того, что «молоток - это не всегда решение».

В этом случае «с» не является вашим решением: вы должны вывести эту бизнес-логику из Ваша форма в вашем модуле данных. Это не нарушает Закон Деметры , как mghie (Майкл Хике), который уже прокомментировал.

Возможно, ваш пример был просто иллюстративным, но если вы на самом деле используете такой код в своих проектах вот что вы должны сделать вместо этого:

procedure TLongNameDataModule.AddToLongNameTable1(const NewField1Value: string);
begin  
  LongNameTable1.Insert;
  LongNameTable1_Field1.Value := NewField1Value;
  LongNameTable1_Field2.Value := LongNameTable2_LongNameField1.Value;
  LongNameTable1_Field3.Value := LongNameTable3_LongNameField1.Value;
  LongNameTable1_Field4.Value := LongNameTable4_LongNameField1.Value;
  LongNameTable1.Post;
end;

И затем вызвать его из своей формы следующим образом:

procedure TMyForm.AddButtonClick(Sender: TObject);
begin  
  LongNameDataModule.AddToLongNameTable1('some value');
end;

Это эффективно избавляет вас от оператора with и делает ваш код более легким в обслуживании.

курс, заключающий строки Delphi в одинарные кавычки, также поможет компилировать их; -)

4
ответ дан 27 November 2019 в 15:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: