如何缓存函数布尔结果
How to cache function Boolean result
我有这个功能:
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
可以初始化为 nil 就完美了(我认为)。
此代码可以正常工作,并且已正确实现。可为空的布尔值或三态枚举会读起来更好,但从根本上讲,逻辑是相同的。
不过,这是一种笨拙的方法,它调用了一个 Word 实例,然后将其丢弃。我个人会阅读注册表以检查 COM 对象是否已注册。我不会尝试预测对象已注册但无法创建的情况。在我看来,这是一个例外情况,应该在它发生时处理,而不是在此之前。
另一种方法就是不尝试提前检查 Word COM 对象是否可用。只需继续并在需要使用对象时尝试创建对象即可。如果失败,请处理。如果你想记住它失败了,那就记住吧。但是你真的应该避免创建对象两次,一次就足够了。
对缓存结果使用 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;
这也可以用 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;
我有这个功能:
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
可以初始化为 nil 就完美了(我认为)。
此代码可以正常工作,并且已正确实现。可为空的布尔值或三态枚举会读起来更好,但从根本上讲,逻辑是相同的。
不过,这是一种笨拙的方法,它调用了一个 Word 实例,然后将其丢弃。我个人会阅读注册表以检查 COM 对象是否已注册。我不会尝试预测对象已注册但无法创建的情况。在我看来,这是一个例外情况,应该在它发生时处理,而不是在此之前。
另一种方法就是不尝试提前检查 Word COM 对象是否可用。只需继续并在需要使用对象时尝试创建对象即可。如果失败,请处理。如果你想记住它失败了,那就记住吧。但是你真的应该避免创建对象两次,一次就足够了。
对缓存结果使用 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;
这也可以用 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;