如何缓存函数布尔结果



我有这个函数:

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<->CCD_ 2。如果Boolean可以初始化为零,它将是完美的(我认为)。

对缓存的结果使用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;

此代码运行良好,并且实现正确。可为null的布尔值或三态枚举会读起来更好,但从根本上讲,逻辑是相同的。

不过,这是一种严厉而笨拙的方法,调用Word的一个实例,然后将其丢弃。就我个人而言,我会阅读注册表来检查COM对象是否已注册。我不会试图预测对象已注册但无法创建的情况。在我看来,这是一个例外情况,应该在发生时处理,但不能在发生之前处理。

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

这也可以通过Variant类型来完成。变体设置为"未指定"。(参考)

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;

最新更新