避免“变量可能尚未初始化”

时间:2010-04-26 22:29:42

标签: delphi refactoring compiler-warnings

我最近碰到了一个看起来像这样的例程:

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;来摆脱这个警告,但我想知道是否可能没有更好的方法来构建它来避免这个问题。有人有什么想法吗?

5 个答案:

答案 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则不会设置两次