避免"变量可能尚未初始化"

Mas*_*ler 12 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;
Run Code Online (Sandbox Code Playgroud)

这使得Variable 'local' might not have been initialized即使你可以通过阅读,除非初始化它的代码分支已经运行,你不会碰到该行代码告诉.

现在,我可以local := 0;在程序的顶部添加一个无用的东西来摆脱这个警告,但我想知道是否可能没有更好的方法来构建它来避免这个问题.有人有主意吗?

Nei*_*eil 12

我将它分成两个for循环 - 一个用于当flag为true时,一个用于当flag为false时.作为额外的好处,您不必在每次迭代时都执行if语句.

  • 因为在“ if NOT标志”分支中,变量将在使用之前进行初始化,而在备用流程中,根本不会使用(或引用)该变量。 (2认同)

Chr*_*ton 6

IMO,对0的赋值在这里并不是无用的 - 它对于维护性是有益的.因此,您可以节省一些人(可能是您未来的自己),而不必花费一两分钟来确定代码的工作原理.设计聪明可能会丢失(即使是你!)

  • 有时这个赋值是有害的,因为它关闭了编译器,但只是隐藏了一个语义错误:假设Mason的继承者错误地将if条件替换为`if not flag then`.那么警告是合理的,但是`local:= 0;`会压制它.所以在这种情况下我会认为它甚至没用,而是一种悲观. (2认同)

Del*_*ics 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;
Run Code Online (Sandbox Code Playgroud)

这基本上重申了neilwhitaker1给出的答案,但也清楚地表明局部变量的初始化将被带入条件分支,这是解决编译器警告的问题(只有在分支中使用的变量时才会发出警告)它可能没有被初始化 - 在根本不使用它的分支中不会发出这样的警告,并且在使用它的分支中它肯定会被初始化,并且因为它用在一个分支中你将不会得到一个"可能不会被使用"的提示.

注意:如果每个分支都有"//其他"的任何一个,那么这些当然可以重构为本地嵌套过程以避免重复.

另请注意:在上面的代码中,我已经纠正了for循环中的循环索引溢出.:)

  • 补充说明:两个分支看起来不同.也许将它分成两个函数:"if flag然后DoSomethingSimple,否则DoSomethingExpensive;" (2认同)