dcc32警告UnloadProcs.pas(59):W1035函数'GetType'的返回值可能未定义

时间:2012-12-19 14:07:25

标签: delphi function build warnings delphi-xe2

有数据类型

type
TDataTypeId = (DataTypeId_String, DataTypeId_SmallInt, DataTypeId_Integer, DataTypeId_Word,
               DataTypeId_Boolean, DataTypeId_Float, DataTypeId_Currency,
               DataTypeId_BCD, DataTypeId_FmtBCD, DataTypeId_Date,
               DataTypeId_Time, DataTypeId_DateTime, DataTypeId_TimeStamp,
               DataTypeId_Bytes, DataTypeId_VarBytes, DataTypeId_Blob,
               DataTypeId_Memo, DataTypeId_Graphic, DataTypeId_fmtMemo,
               DataTypeId_FixedChar, DataTypeId_WideChar, DataTypeId_LargeInt,
               DataTypeId_Array, DataTypeId_FixedWideChar, DataTypeId_WideMemo);

有一个函数接受包含这种类型值之一的行,返回该值

Function GetType(str: string): TDataTypeId;
var
typeidx: TDataTypeId;
typestr: string;
begin
for typeidx := Low(TDataTypeID) to High(TDataTypeID) do
 begin
  typestr:=GetEnumName(TypeInfo(TDataTypeId),Ord(typeidx));
  typestr:=Copy(typestr, 12, length(typestr)-11);
  //Memo.Lines.Add(typestr+'\n');
  if (AnsiCompareStr(str, typestr)=0) then
     Result:=typeidx
 end;
 end;

因此,有一个程序集

[dcc32 Warning] UnloadProcs.pas(59): W1035 Return value of function 'GetType' might be undefined

如何转换没有出现警告的功能?

3 个答案:

答案 0 :(得分:5)

编译器警告是准确的。如果if语句永远不会计算为True,因为未找到匹配项,则循环不会分配给Result。然后函数退出而不指定值。

您的选择:

  1. 在循环完成后为Result分配一个值,表示未找到匹配项。
  2. 在循环完成后引发异常。
  3. 我还建议您在分配exit后立即Result。当你找到答案时,没有必要继续循环。

    我可能会写这样的函数:

    Function GetType(str: string): TDataTypeId;
    var
      typestr: string;
    begin
      for Result := low(Result) to high(Result) do
      begin
        typestr := GetEnumName(TypeInfo(TDataTypeId),Ord(typeidx));
        typestr := Copy(typestr, 12, length(typestr)-11);
        if AnsiSameStr(str, typestr) then
          exit;
      end;
      raise EEnumNotFound.CreateFmt('Enum not found: %s', [str]);
    end; 
    

    注意使用Result变量作为循环变量。这是惯用的,可以减少您声明的局部变量的数量。

    我同意您可以使用GetEnumValue更有效地解决您的问题,但我想向您展示如何以惯用的方式处理编译器警告。

答案 1 :(得分:1)

关于在这样的循环中使用result的一般方法,以下是编写函数的方法:

Function GetType(const str: string): TDataTypeId;
var
typestr: string;
begin
 for result := Low(TDataTypeID) to High(TDataTypeID) do
 begin
  typestr:=GetEnumName(TypeInfo(TDataTypeId),Ord(result));
  typestr:=Copy(typestr, 12, length(typestr)-11);
  //Memo.Lines.Add(typestr+'\n');
  if (AnsiCompareStr(str, typestr)=0) then
     exit; // if found, returns result value
 end;
 result := DataTypeId_String; // returns STRING type by default
end;

这是您可以在循环范围之外使用循环变量的唯一情况之一。生成的代码是正确的,并进行了优化。

我认为您应该更好地定义TDataTypeId这样的专用DataTypeId_Unknown项,或者如果找不到则会引发异常。

答案 2 :(得分:0)

其他人已经解释了警告,但更好的例程实现将是:

uses
  TypInfo, ConvUtils;

Function GetType(str: string): TDataTypeId;
var idx: Integer;
begin
  idx := GetEnumValue(TypeInfo(TDataTypeId), 'DataTypeId_'+str);
  if(idx <> -1)then Result := TDataTypeId(idx)
  else RaiseConversionError('Unknown typeID name: '+str);
end;

即不需要遍历所有枚举值并将它们作为字符串进行比较,而是使用GetEnumValue函数。