每当我使用以下结构时,我仍然无法弄清楚如何摆脱有关未初始化变量的警告,即使我知道这种情况永远不会发生。
long list of user ids which can be queried for currently authenticated user, if this user in department b, than here will be list of user ids in departments B and C, task has no connection to department, only to user
W1036变量' lNumber'可能尚未初始化
我找到了3个解决方案,但我不喜欢它们中的任何一个。特别是有更多的变量或陈述。有没有其他方法可以避免这种情况?
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;
和{$WARN USE_BEFORE_DEF OFF}
{$WARN USE_BEFORE_DEF ON}
并在开头使用else Exit;
答案 0 :(得分:6)
通过执行以下操作
String temptime= "1715UTC";
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HHmm");
simpleDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
Date myDate = simpleDateFormat.parse(temptime);
long time= Long.toString(myDate.getTime());
也许是一个更好的异常文本,甚至根本不会引发异常(并为lNumber分配不同的值),但是提出异常确实有一个好处,例如,如果你想要在六个月之后添加新的异常案件价值。
关键在于编译器是正确的。枚举的基础结构是某种形式的(无符号)整数,因此枚举完全有可能包含非法值,例如27。在实践中有很多方法可以产生。因此,如果您正在编写完整的代码,则需要满足这种可能性。编译器只是警告你,你没有提供这种可能性。
答案 1 :(得分:3)
我发现这个编译器警告有点令人失望。毕竟,编译器肯定可以检测到您已经涵盖了枚举类型的所有可能值。我不相信你应该担心你在枚举类型中加入了一个无效的序数,如果确实这就是这个警告背后的想法。
无论如何,我个人使用以下帮助方法来解决这个问题:
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;