Ответ 1
Я бы разделил его на два for-loops - один для флага, когда флаг true, а один для флага - false. В качестве дополнительного преимущества вам не придется выполнять if-инструкцию на каждой итерации.
Недавно я столкнулся с процедурой, которая выглядит примерно так:
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;
в начало процедуры, но мне интересно, может быть, нет лучшего способа структурировать это, чтобы избежать проблемы. У кого-нибудь есть идеи?
Я бы разделил его на два for-loops - один для флага, когда флаг true, а один для флага - false. В качестве дополнительного преимущества вам не придется выполнять if-инструкцию на каждой итерации.
IMO, назначение 0 здесь бесполезно - это выгодно для maintanability. Таким образом, вы можете спасти кого-то (возможно, ваше будущее) от необходимости потратить минуту или две, чтобы определить, работает ли код. И умение дизайна, вероятно, будет потеряно на них (даже если это вы!)
Рефакторинг кода, который содержит два отдельных потока на основе параметра флага:
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, но также дает понять, что инициализация переменной локальная должна быть введена внутри условной ветки, что является тем, что обращается к предупреждению компилятора (которое испускается только в том случае, если varialbe используется в ветке, где она не может быть инициализирована - в ветке, которая ее вообще не использует, не должно быть выбрано такое предупреждение, а в ветки, где она используется, обязательно будет инициализирована, и поскольку он используется в одной ветке, и вы не получите подсказки "не могут быть использованы".
ПРИМЕЧАНИЕ. Если какое-либо из "//что-то еще" является общим для каждой ветки, они, конечно, могут быть реорганизованы как локальные, вложенные процедуры, чтобы избежать дублирования.
ТАКЖЕ ПРИМЕЧАНИЕ: В приведенном выше коде я скорректировал превышение индекса цикла в цикле for.:)
добавление локального: = 0 хорошего решения.
поскольку я знаю подсказки, потому что это могут быть неинициализированные переменные. если вы всегда назначаете переменные значения для инициализации и используете блоки try finally для проверки ошибок, вы не можете иметь никаких проблем.
поскольку я знаю, что компилятор дает подсказки, потому что, даже если вы проверяете флаг во время выполнения, ваша переменная может быть не назначена, и ваш код не может работать как ожидалось.
извините за мой плохой английский:)
i изменил бы верхнюю часть вашей процедуры на
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 устанавливается независимо от того, какой флаг, тем более, что он не устанавливается дважды, если флаг false