W1035:函数'Take'的返回值可能未定义

时间:2014-01-25 14:25:43

标签: delphi exception exception-handling try-catch

我有一个从字典中弹出元素的函数,如果出现任何问题,应该抛出异常。代码看起来很不错。

type 
  ENoSuchElementException = class(Exception);
var
  FResults: TDictionary<Cardinal, TObject> = TDictionary<Cardinal, TObject>.Create;
  FLock: TCriticalSection = TCriticalSection.Create;

/// <exceptions cref="ENoSuchElementException">Element does not exist</exceptions>
function Take(Id: Cardinal): TObject;
begin    
  FLock.Acquire;
  try
    try
      Result := FResults[Id]; // here may throw exception
      FResults.Remove(Id);
    except
      on E: Exception do
      begin
        raise ENoSuchElementException.Create(E.ToString);
      end;
    end;
  finally
    FLock.Release;
  end;
end;

但是Delphi XE4编译器抱怨W1035: Return value of function 'Take' might be undefined

我突然很困惑。如果抛出异常,为什么代码仍然期望返回值?这是否意味着try...finally会吃掉这个例外?有人可以指出我的代码问题吗?

已解决:正如大卫所说,try...except应移至外部。谢谢!

2 个答案:

答案 0 :(得分:2)

David Heffernan给出了最直接的答案,但另一种方法是完全避免try / except阻止并使用TryGetValue TDictionary方法。更进一步,你可以想要摆脱单独的锁定对象:

var FResults: TDictionary<Cardinal, TResult>;

function Take(Id: Cardinal): TResult;
begin    
  TMonitor.Enter(FResults);
  try
    if FResults.TryGetValue(Id, Result) then
      FResults.Remove(Id)
    else
      Abort;
  finally
    TMonitor.Exit(FResults);
  end;
end;

TMonitor历史上存在重大错误,但在XE4中也没问题。

答案 1 :(得分:1)

这似乎是32位编译器报告的误报。 64位编译器不会为您的代码报告警告。并且64位编译器是正确的。也许32位编译器看到你正在捕获异常并且不会继续检测到你总是随后引发另一个异常。

解决32位编译器错误诊断的一种方法是使try / except成为最外层的块。请考虑以下SSCCE:

{$APPTYPE CONSOLE}

uses
  SysUtils;

procedure Foo;
begin
end;

function Take1(const Id: Integer): Integer;
begin
  try
    try
      Foo;
      Result := 42;
    except
      on E:Exception do
      begin
        raise Exception.Create(E.ToString);
      end;
    end;
  finally
  end;
end;

function Take2(const Id: Integer): Integer;
begin
  try
    try
      Foo;
      Result := 42;
    finally
    end;
  except
    on E:Exception do
    begin
      raise Exception.Create(E.ToString);
    end;
  end;
end;

begin
end.

编译器的输出是:

[dcc32 Warning] W1035 Return value of function 'Take1' might be undefined

因此,Take1是我的代码的简化版本。 32位编译器警告这一点。并Take2交换exceptfinally的顺序。并且编译器不会发出警告。

也许这种解决方法不适合你,但你必须提出这种性质的东西。

底线是您的分析正确,编译器错误。