如何缓存函数布尔结果

时间:2015-12-06 09:08:32

标签: delphi optimization delphi-7

我有这个功能:

var
  _WordApplicationExistsCache: Integer = -1; // Cache result

function WordApplicationExists: Boolean;
var
  WordObj: OleVariant;
begin
  if (_WordApplicationExistsCache = -1) then
  begin
    Result := False;
    try
      try
        WordObj := CreateOleObject('Word.Application');
        WordObj.Visible := False;
        WordObj.Quit;
        WordObj := Unassigned;
        Result := True;
      except
        // error
      end;
    finally
      _WordApplicationExistsCache := Ord(Result); // 0;1
    end;
  end
  else
  begin
    Result := Boolean(_WordApplicationExistsCache);
  end;
end;

我试图在应用程序生命周期中只调用一次此函数。我可能根本不会调用这个函数。

这是正确的模式吗?这可以做得更好吗?

编辑: 我能想到的另一种方法是,在这种情况下使用2个变量:

var
  _WordApplicationExistsInitialized: Boolean = False; // Cache result
  _WordApplicationExistsCacheResult: Boolean; // Undefined ?

function WordApplicationExists: Boolean;
var
  WordObj: OleVariant;
begin
  if not _WordApplicationExistsInitialized then
  begin
    _WordApplicationExistsInitialized := True;
    Result := False;
    try
      try
        WordObj := CreateOleObject('Word.Application');
        WordObj.Visible := False;
        WordObj.Quit;
        WordObj := Unassigned;
        Result := True;
      except
        // error
      end;
    finally
      _WordApplicationExistsCacheResult := Result;
    end;
  end
  else
  begin
    Result := _WordApplicationExistsCacheResult;
  end;
end;

关于第一个版本的一点错误是类型转换Boolean< - > Integer。如果Boolean可以初始化为零,那就完美了(我想)。

3 个答案:

答案 0 :(得分:6)

对缓存的结果使用TriState类型。

type
  TTriState = ( tsUnknown, tsFalse, tsTrue );

var
  _WordApplicationExists : TTriState = tsUnknown;

function WordApplicationExists : Boolean;
var
  WordObj: OleVariant;
begin
  if _WordApplicationExists = tsUnknown 
  then
    try
      WordObj := CreateOleObject('Word.Application');
      WordObj.Visible := False;
      WordObj.Quit;
      WordObj := Unassigned;
      _WordApplicationExists := tsTrue;
    except
      _WordApplicationExists := tsFalse;
    end;

  Result := _WordApplicationExists = tsTrue;
end;

答案 1 :(得分:4)

此代码可以正常工作,并且已正确实现。可以为空的布尔值或三态枚举将更好地读取,但从根本上说逻辑将是相同的。

然而,这是一种笨重而笨重的方法,调用一个然后被丢弃的Word实例。我个人会阅读注册表来检查COM对象是否已注册。我不会尝试预测对象已注册但无法创建的情况。在我看来,这是一个特殊的情况,应该在它发生时处理,但不是之前。

另一种方法是不要提前检查Word COM对象是否可用。只需继续并在需要使用它时尝试创建对象。如果失败,请处理。如果您想记住它失败了,请这样做。但是你真的应该避免在一次就足够的时候创建两次。

答案 2 :(得分:0)

这也可以使用Variant类型完成。变体设置为“未分配”。 (reference

var
  _WordApplicationCanCreate: Variant; // Unassigned (VType = varEmpty)

function WordApplicationCanCreate: Boolean;
var
  WordObj: OleVariant;
begin
  if VarIsEmpty(_WordApplicationCanCreate) then
  try
    WordObj := CreateOleObject('Word.Application');
    WordObj.Visible := False;
    WordObj.Quit;
    WordObj := Unassigned;
    _WordApplicationCanCreate := True;
  except
    _WordApplicationCanCreate := False;
  end;

  Result := _WordApplicationCanCreate = True;
end;