delphi - case语句中未初始化的变量

标签 delphi delphi-xe6

即使我知道这永远不会发生,我仍然无法弄清楚如何在使用以下结构时摆脱有关未初始化变量的警告。

TCustomEnum = (ceValue1, ceValue2, ceValue3);

function DoSomething(LI_Enum: TCustomEnum): Integer;
var
  lNumber : Integer;
begin
  case LI_Enum of
    ceValue1 : lNumber := 1;
    ceValue2 : lNumber := 2;
    ceValue3 : lNumber := 3;
  end;
  Result := 2 * lNumber;
end;



W1036变量“ lNumber”可能尚未初始化


我找到了3个解决方案,但我不喜欢其中任何一个。特别是带有更多变量或语句。还有其他方法可以避免这种情况吗?


使用{$WARN USE_BEFORE_DEF OFF}{$WARN USE_BEFORE_DEF ON}包装功能
在每种情况下,在开头都使用else Exit;Result := 0
初始化每个变量,尽管永远不会使用该值

最佳答案

我发现此编译器警告有些令人失望。毕竟,编译器肯定可以检测到您已经涵盖了枚举类型的所有可能值。我不认为您应该担心是否在枚举类型中输入了无效的序数,即使这确实是此警告背后的想法。

无论如何,我个人都使用以下辅助方法来解决此问题:

procedure RaiseAssertionFailed; overload;
procedure RaiseAssertionFailed(var v1); overload;
procedure RaiseAssertionFailed(var v1,v2); overload;

....

procedure DoRaiseAssertionFailed;
begin
  raise EAssertionFailed.CreateFmt(
    'A critical error has occurred:'+ sLineBreak + sLineBreak +
    '      Assertion failed at %p.'+ sLineBreak + sLineBreak +
    'In order to avoid invalid results or data corruption please close the program and report '+
    'the above error code along with any other information relating to this problem.',
    [ReturnAddress]
  ) at ReturnAddress;
end;

procedure RaiseAssertionFailed;
asm
  JMP    DoRaiseAssertionFailed;
end;

procedure RaiseAssertionFailed(var v1);
asm
  JMP    DoRaiseAssertionFailed;
end;

procedure RaiseAssertionFailed(var v1,v2);
asm
  JMP    DoRaiseAssertionFailed;
end;


您的代码将变为:

function DoSomething(LI_Enum: TCustomEnum): Integer;
var
  lNumber : Integer;
begin
  case LI_Enum of
    ceValue1 : lNumber := 1;
    ceValue2 : lNumber := 2;
    ceValue3 : lNumber := 3;
  else
    RaiseAssertionFailed(lNumber);
  end;
  Result := 2 * lNumber;
end;


这与@Dsm概述的方法非常相似。如果使用该方法,则编译器可以看到您正在引发异常,并且知道lNumber不需要初始化。

我更喜欢将引发异常包装到共享函数中。这样,我不需要一次又一次地写相同的错误消息。 DRY原理的应用。

但是,如果执行此操作,然后将引发移到共享函数中,则编译器将无法确定该函数将引发异常。因此,无类型的var参数。这使您可以将变量标记为可能被修改,从而消除编译器警告。

还有一种方法是声明一个异常类,该异常类在其无参数构造函数中提供了文本。

type
  EInternalError = class(Exception)
  public
    constructor Create;
  end;

constructor EInternalError.Create;
begin
  inherited Create(
    '...' // your text goes here
  );
end;


然后您的代码变为:

function DoSomething(LI_Enum: TCustomEnum): Integer;
var
  lNumber : Integer;
begin
  case LI_Enum of
    ceValue1 : lNumber := 1;
    ceValue2 : lNumber := 2;
    ceValue3 : lNumber := 3;
  else
    raise EInternalError.Create;
  end;
  Result := 2 * lNumber;
end;

关于delphi - case语句中未初始化的变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41737878/

相关文章:

excel - 自定义从delphi导入的excel文件

delphi - 在 Delphi 3 中重现 UInt64

delphi - MainFormOnTaskbar + 工具提示导致焦点窃取

delphi - 当直接将对象实例作为 const 接口(interface)参数传递时,编译器是否应该提示/警告?

delphi - 使用取消和终止处理程序正确构建 ParallelTask​​ (IOmniParallelTask​​)

delphi - GetAdaptersInfo 在 Delphi XE6 上不起作用

delphi - 将项目加载到 Delphi XE6 时出现随机错误

delphi - TTimer 的准确度如何?

Delphi 编译器警告将有符号传递给无符号

delphi - for ... in 带接口(interface)