我最近碰到了一个看起来像这样的例程:
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;
来摆脱这个警告,但我想知道是否可能没有更好的方法来构建它来避免这个问题。有人有什么想法吗?
答案 0 :(得分:11)
我将它分成两个for循环 - 一个用于当flag为true时,一个用于当flag为false时。作为额外的好处,您不必在每次迭代时都执行if语句。
答案 1 :(得分:6)
IMO,0的赋值在这里毫无用处 - 它对于可维护性是有益的。因此,您可以节省一些人(可能是您未来的自己),而不必花费一两分钟来确定代码的工作原理。设计聪明可能会在他们身上丢失(即使是你!)
答案 2 :(得分:6)
根据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 变量的初始化将被带入条件分支,这就是解决了编译器警告(只有在可能没有初始化的分支中使用的varialbe时才会发出警告 - 在根本不使用它的分支中不会发出这样的警告),并且在使用它的分支中它是肯定会被初始化,并且由于 在一个分支中使用,你也不会得到“可能不会被使用”的提示。
注意: 如果每个分支都有“//其他”的任何一个,那么这些当然可以重构为本地,嵌套避免重复的程序。
还注意: 在上面的代码中,我更正了for循环上的循环索引溢出。 :)
答案 3 :(得分:1)
添加local:= 0好解决方案。
因为我知道提示因为可以是未初始化的变量。如果你总是为启动分配变量值并使用try finally块进行错误检查,你就不会遇到任何问题。
因为我知道编译器给出提示,因为即使你在运行时检查标志,你的变量也可以被取消分配,你的代码也无法按预期运行。
抱歉我的英语不好:)答案 4 :(得分:1)
我会将程序的顶部更改为
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而不管是什么标志,如果flag为false则不会设置两次