Можно ли использовать NIL для объекта Sender? - PullRequest
4 голосов
/ 14 февраля 2012

Недавно меня попросили автоматизировать небольшую подпрограмму, которая представляла собой серию записей данных и любые две из четырех потенциальных кнопок, которые пользователь мог выбрать после просмотра анализа записи.Босс сказал, что когда пользователи видят, что анализ тратит время, так как пользователи неизменно выбирали номер один в списке кнопок, и он был готов согласиться с моими догадками для всех, кроме лучших его пользователей.Таким образом, он хотел, чтобы добавилась НОВАЯ серия кнопок, предлагающих «Обрабатывать автоматически», «Обрабатывать вручную» и «Обрабатывать индивидуально».Последняя кнопка просто запустит уже существующий код.Вторая кнопка по сути ничего не сделает и просто выйдет.Первая кнопка?Ну, вот в чем дело.

Я решил использовать пару флагов, а затем использовать автоматический путь, просто имитирующий нажатие любой дополнительной кнопки, основываясь на анализе.Проблема заключалась в том, что вызов Button1Click (Sender) был невозможен, поскольку процедура, выполняющая анализ, называлась RunAnalysis и не была привязана к конкретному объекту для прохождения объекта TObject.В конце концов я реорганизовал внутренности метода Button1Click в Button1Pressed, а затем вызвал THAT из Button1Click.Таким образом, я смог вызвать Button1Pressed из RunAnalysis.

Избегаемым путем было бы вызвать Button1Click (Nil).Я не пробовал, так как у меня было простое решение (кстати, спасибо Modelmaker).Но мой вопрос в том, сработала бы нулевая ссылка или это привело бы к катастрофе.Мог ли я вызвать более высокую функцию (случайно), у которой был отправитель, ТОЛЬКО чтобы иметь объект отправителя в вызове процедуры?Насколько важен объект Sender, если я не использую ничего, что действительно ссылается на Sender?

Сведения о системе: Delphi 7 в среде программирования Win 7 для использования в Windows XP.

Спасибозаранее за любую мудрость, GM

Ответы [ 4 ]

8 голосов
/ 14 февраля 2012

Я стараюсь по возможности помещать код обработчика событий в другой метод:

procedure TForm1.DoSomething(const Test: Boolean);
begin
  // Do Something based on Test
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  DoSomething(False); // init here
end;

procedure TForm1.CheckBox1Click(Sender: TObject);
begin
  DoSomething(TCheckBox(Sender).Checked);
end;

Поэтому, когда мне нужно вызвать CheckBox1Click(nil), это хороший знак для меня, чтобы вытащить код из обработчика событий в отдельный метод.

6 голосов
/ 14 февраля 2012

Обратный вызов или «событие» ничем не отличается от любой другой функции. Вы можете передать NIL-ссылку куда угодно, если вы (а) написали этот код и знаете, что он нулевой, или (б) вы прочитали этот код и все, что он вызывает, не проверяя на ноль, и знаете, что он нулевой. .

Некоторые программисты свободно используют NIL, а некоторые считают использование параметров NIL плохим стилем. Мой стиль, как правило, «не предполагайте, что Отправитель назначен, и не предполагайте, что он имеет определенный тип», что приводит к большому количеству проверочного кода в моих обработчиках событий, но в другом коде, отличном от моего, он варьируется в широких пределах и Итак, первое правило кодирования приходит; «Не делайте предположений. Прочитайте код».

5 голосов
/ 14 февраля 2012

Вы можете использовать nil в качестве параметра для события TNotify (или любого другого, ожидающего Sender), если код не ссылается на Sender:

procedure TForm1.Button1Click(Sender: TObject);
begin
  DoSomeStuff(nil);
end;

procedure TForm1.DoSomeStuff(Sender: TObject);
begin
  // Safe
  DoSomeOtherStuff;
  // Safe

  // Do stuff with Sender
  if Sender is TButton then
    TButton(Sender).Caption := 'In DoSomeStuff'

  // NOT safe!
  with TButton(Sender) do
  begin
    Caption := 'In DoSomeStuff';
  end;
end;
2 голосов
/ 14 февраля 2012

Краткий ответ - да.

Я использую его, чтобы определить, был ли (скажем) пункт «Событие» в меню пользователем или вызван непосредственно кодом.

...