Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ssl/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi 避免";变量可能尚未初始化";_Delphi_Refactoring_Compiler Warnings - Fatal编程技术网

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

Delphi 避免";变量可能尚未初始化";,delphi,refactoring,compiler-warnings,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 fo

我最近遇到了一个类似这样的例程:

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;
程序TMyForm.DoSomething(列表:TList;常量标志:boolean);
变量
局部:整数;
开始
如果旗子那么
//做点什么
else local:=计算某物的费用函数调用;
//做点别的
对于i:=0的列表。计数do
如果旗子那么
//做点什么
否则,如果列表[i].IntValue>local,则//此处出现警告
//做点别的
结束;

这使得
变量“local”可能尚未初始化
,即使通过读取代码可以看出,除非初始化该行的代码分支已运行,否则不会命中该行


现在,我可以通过添加一个无用的
local:=0
位于过程的顶部,但我想知道是否有更好的方法来构造它以避免问题。有人有什么想法吗?

我会把它分成两个for循环——一个用于标记为true时,另一个用于标记为false时。作为一个额外的好处,您不必在每次迭代时都执行if语句。

IMO,0的赋值在这里并不是无用的,它有利于可维护性。因此,您将使某人(可能是您未来的自己)不必花费一两分钟来确定代码是否有效。而且设计的巧妙性很可能会在他们身上消失(即使是你!)

添加local:=0好的解决方案

正如我所知,提示可能是未初始化的变量。如果您总是为初始化分配变量值,并使用try-finally块进行错误检查,那么您就不会遇到任何问题

据我所知,编译器会给出提示,因为即使您在运行时检查标志,您的变量也可能会被取消分配,并且您的代码无法按预期运行


对不起,我的英语不好:)

我会将您的程序顶部更改为

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;
程序TMyForm.DoSomething(列表:TList;常量标志:boolean);
变量
局部:整数;
开始
如果旗子那么
开始
本地:=0;
//做点什么
结束
else local:=计算某物的费用函数调用;
等等


这样,无论标志是什么,都会设置Local,因此如果标志为false,则不会设置两次。

根据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;
程序TMyForm.DoSomething(列表:TList;常量标志:boolean);
变量
局部:整数;
开始
如果旗子那么
开始
//做点什么
//做点别的
对于i:=0到Pred(list.Count)do
//做点什么
结束
其他的
开始
本地:=计算某事物的费用函数调用;
//做点别的
对于i:=0到Pred(list.Count)do
如果列表[i].IntValue>local,则
//做点别的
结束;
结束;
这从本质上重申了neilwhitaker1给出的答案,但也清楚地表明,局部变量的初始化将被带到条件分支内部,这就是解决编译器警告的方法(仅当变量在未进行初始化的分支中使用时,才会发出警告-在根本未使用该变量的分支中,不得发出此类警告,在使用该变量的分支中,肯定会进行初始化,并且由于变量在一个分支中使用,您也不会得到“可能未使用”提示

注意:如果任何“//something”对每个分支都是通用的,那么当然可以将它们重构为本地嵌套过程,以避免重复


另请注意:在上面的代码中,我已经纠正了for循环上循环索引的过度运行。

我认为预初始化变量是一个很好的做法,因为它们指向内存中的随机数据,如果您不注意,可能会导致应用程序中出现意外行为:)我认为C#甚至不允许您运行该代码,因为本地代码没有初始化。哦,我知道这是一种很好的做法。我只是想知道是否有更好的方法来编写代码,而我不需要初始化它,以避免收到警告。(关闭警告是欺骗。)我想编译器并没有那么复杂。它可能只是看到局部可能被初始化。“即使你可以通过阅读代码来判断,除非初始化它的代码分支已经运行,否则你不会到达那一行”——编译器是智能的,但没有那么智能。您正在做的一件微妙的事情是确保如果本地未初始化,则永远不会访问它,并且它会在警告的一侧出错。还应该有人指出循环计数器上的索引过度运行。;)我想说的可能性很小,但是您当然可以用这两种方法编写例程,然后比较每种情况下代码的CPU反汇编视图,以自行确定。不需要:惊奇:;)是的,这是一个不错的性能优化,但我看不出它如何消除编译器警告。因为在“if NOT flag”分支中,变量在使用之前会被初始化,而在备用流中它根本不会被使用(或引用)。@Mason,它应该消除警告,因为在flag=true分支中,您从未尝试访问
local
的值。试试看。补充说明:这两个分支看起来很不一样。可能将其分成两个函数:“if flag then DoSomethingSimple else DoSomethingExpensive”;这是原作者的进一步重构决策——如果不知道“某物”和“其他某物”是什么,就不可能说这两个分支有多相似有时,这种赋值是有害的,因为它关闭了编译器,但这只是隐藏了一个语义错误:假设Mason的继任者错误地用
if not标志then
替换了if条件。然后警告将是合理的,但
local:=0将抑制它。因此,在这种情况下,我会认为它甚至是无用的,而是悲观的。