如果Windows运行时类型引发COM错误.NET似乎经常(或总是?)将此错误包装到Exception
实例中。错误消息包含COM HRESULT错误代码。例如,当使用带有AES-CBC的新Cryptographic API时,错误的缓冲区长度会导致Exception
消息“提供的用户缓冲区对请求的操作无效。(Exception from HRESULT: 0x800706F8
)”。< / p>
那么,我们应该如何处理这些例外?我们是否应该从异常中读取HRESULT
代码以了解哪种异常是什么?在经典的.NET中,我会得到一个CryptographicException
,我可以用它来区分加密错误和其他错误。
我不明白的另一件事是Microsoft代码质量规则规定一个人永远不应该抛出Exception但总是派生类型。原因是不应该强迫任何人抓住一般Exception
来抓住更多致命的例外,例如OutOfMemoryException
。另一个规则是,永远不应该在库中捕获Exceptio
n。如果我们被迫在Windows应用商店应用或WinRT库中捕获Exception
,我们如何才能遵循这些政策?
顺便说一下:Clemens Vasters shows in his blog how we can catch Exception while avoiding to catch fatal exception。我认为捕捉Exception
不再是坏代码。
答案 0 :(得分:4)
可以捕获Exception
,通过打开HRESULT处理特定错误,并在错误“意外”时重新抛出Exception
。例如,
try
{
// ...
}
catch (Exception ex)
{
switch (ex->HResult)
{
case E_INVALID_USER_BUFFER: // 0x800706f8
// handle invalid buffer case...
break;
default:
// Unexpected exception; re-throw:
throw;
}
}
(我会注意到,提供无效的缓冲区听起来更像是一个逻辑错误,而不是运行时错误,所以我想知道是否应该抓住这个特殊的异常。)
或者,更通用的解决方案是编写一个函数或一组函数来处理已知HRESULT的Exception
并重新抛出更具体的异常。例如,
static void HandleKnownExceptions(Action f)
{
try
{
f();
}
catch (Exception ex)
{
// Detect expected HRESULTs and throw the more-specific exception
// type for each.
}
}
这两种方法在C ++和C#中同样有效。
请注意,不一定是平台或其他组件直接抛出Exception
的情况。在Windows运行时ABI层,没有例外:HRESULT在ABI边界上报告所有错误。 CLR将少数已知的HRESULT转换为更具体的异常类型,但它无法执行常规转换。