Предотвращение “переменной, возможно, не было инициализировано”

Я недавно натыкался на стандартную программу, которая выглядит примерно так:

procedure TMyForm.DoSomething(list: TList<TMyObject>; const flag: boolean);
var
  local: integer;
begin
  if flag then
    //do something
  else local := ExpensiveFunctionCallThatCalculatesSomething;

  //do something else
  for i := 0 to list.Count do
    if flag then
      //do something
    else if list[i].IntValue > local then //WARNING HERE
        //do something else
end;

Это дает Variable 'local' might not have been initialized даже при том, что можно сказать путем чтения кода, что Вы не поразите ту строку, если ответвление кода, которое инициализирует его, не работало.

Теперь, я мог избавиться от этого предупреждения путем добавления бесполезного local := 0; наверху процедуры, но интересно, не могло ли быть лучшего способа структурировать это для предотвращения проблемы. У кого-либо есть какие-либо идеи?

12
задан Mason Wheeler 26 April 2010 в 22:29
поделиться

5 ответов

Я бы разделил его на два цикла for - один для случая, когда флаг равен true, а другой - когда флаг равен false. В качестве дополнительного преимущества вам не придется выполнять оператор if на каждой итерации.

12
ответ дан 2 December 2019 в 05:53
поделиться

Выполните рефакторинг кода, чтобы он содержал два отдельных потока на основе параметра flag:

procedure TMyForm.DoSomething(list: TList<TMyObject>; const flag: boolean);
var
  local: integer;
begin
  if flag then
  begin
    //do something
    //do something else
    for i := 0 to Pred(list.Count) do
      //do something
  end
  else
  begin
    local := ExpensiveFunctionCallThatCalculatesSomething;

    //do something else
    for i := 0 to Pred(list.Count) do
      if list[i].IntValue > local then
        //do something else
  end;
end;

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

ПРИМЕЧАНИЕ: Если какие-либо из «// что-то еще» являются общими для каждой ветви, их, конечно, можно реорганизовать как локальные, вложенные процедуры, чтобы избежать дублирования.

ТАКЖЕ ПРИМЕЧАНИЕ: код выше Я исправил превышение индекса цикла в цикле for. :)

6
ответ дан 2 December 2019 в 05:53
поделиться

добавление local: = 0 хорошего решения.

как я знаю подсказки, потому что это могут быть неинициализированные переменные. если вы всегда назначаете значения переменных для инициации и используете блоки try finally для проверки ошибок, у вас не будет никаких проблем.

Насколько мне известно, компилятор дает подсказки, потому что даже если вы отметите флаг во время выполнения, ваша переменная может быть не назначена, и ваш код не может работать должным образом.

извините за мой плохой английский :)

1
ответ дан 2 December 2019 в 05:53
поделиться

ИМО, присвоение 0 здесь не бесполезно - это полезно для удобства обслуживания. Так вы избавите кого-то (возможно, себя в будущем) от необходимости потратить минуту или две на то, чтобы определить, работает ли код. И дизайнерская смекалка им наверняка потеряется (даже если это вы!)

6
ответ дан 2 December 2019 в 05:53
поделиться

Я бы изменил начало вашей процедуры на

procedure TMyForm.DoSomething(list: TList<TMyObject>; const flag: boolean);
var
  local: integer;
begin
  if flag then
   begin
     local := 0;
     //do something
   end
  else local := ExpensiveFunctionCallThatCalculatesSomething;

и т. Д.

Таким образом, Local устанавливается независимо от того, какой флаг установлен, более того он не устанавливается дважды, если флаг ложный

1
ответ дан 2 December 2019 в 05:53
поделиться
Другие вопросы по тегам:

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