【发布时间】:2016-07-11 13:53:14
【问题描述】:
我有一个图像检测模块,它被封装为一个 COM 模块。我导出了一个Key/Value Getter API,例如:GetImageAttr(UINT key, void* pValue);。我们的产品可能会或可能不会在图像上附加特殊结构,因此我的客户可以通过此 API 查询特定结构。
可能的用法是这样的:
ImageSpecialAttribute attr = {};
HRESULT hr = pImageDetector->GetImageAttr(IMAGE_SPECIAL_ATTRIBUTE, (void*)&attr);
如果图像确实具有这样的附加结构,则返回S_OK 是微不足道的。但如果没有,我应该返回 E_FAIL 还是 S_FALSE?
-
S_FALSE:一切都很好,只是图像没有这个可选属性。
- 强制用户检查 hr == S_OK
- 查询没有此类可选属性的图像不会出错。
-
E_FAIL:不!出了点问题。你不应该查询这个键。
- 客户可以通过 FAILED(hr) 轻松检查
- 使用此键查询此不存在的值是错误的。
已更新,(感谢 Remy Lebeau)
-
HRESULT_FROM_WIN32(ERROR_NOT_FOUND):不!不存在这样的元素/属性。
- 客户可以通过 FAILED(hr) 轻松检查
- 虽然代表错误,但用户通过查看
hr仍然可以知道是什么意思。
【问题讨论】:
-
IMO,任何返回
HRESULT的东西都应该能够使用FAILED()进行测试,所以我对选项 2 投了赞成票。 -
某些语言(例如 Visual Basic)会将
E_代码转换为运行时异常。所以,我的建议是使用类似的规则来决定你的 C++ 函数是抛出失败还是返回状态码。通常,函数应该只在特殊情况下抛出,并且如果它应该中止或中断代码的执行流程。 -
无论您决定采用哪种方式,如果该属性不存在,请确保使用中性值填写
attr。 -
避免使用结构,它们很难正确编组(google IRecordInfo)。请改用接口。该接口上的 IsValid 属性肯定是明智的。避免使用 S_FALSE,没有多少语言运行时允许客户端代码看到该值。并没有多少客户端程序员认为他们应该捕获异常或 E_FAIL 意味着什么。
-
@HansPassant:OLE 到处使用
S_FALSE,没有理由避免它。它不能是该属性不存在的唯一指示,但除了另一种方法之外使用它是完全合理的。