【发布时间】:2010-09-12 04:31:42
【问题描述】:
我正在为现有的引发异常的本机类编写一个 .NET 包装类。在原生 C++ 异常和托管异常之间进行转换的最佳实践是什么?在一对一的基础上捕获并重新抛出(例如 std::invalid_argument -> System.System.ArgumentException)?是否已经在某处绘制了地图?
【问题讨论】:
标签: .net exception error-handling c++-cli
我正在为现有的引发异常的本机类编写一个 .NET 包装类。在原生 C++ 异常和托管异常之间进行转换的最佳实践是什么?在一对一的基础上捕获并重新抛出(例如 std::invalid_argument -> System.System.ArgumentException)?是否已经在某处绘制了地图?
【问题讨论】:
标签: .net exception error-handling c++-cli
据我所知,没有标准映射。我过去所做的是翻译我所知道的,以及 System.Runtime.InteropServices.SEHException 的 catch 块。所有未翻译的异常都将转换为该异常。只要你有一个抛出异常的代码的调试版本,你就应该得到一个很好的堆栈跟踪。然后你可以去看看异常并编写包装器。
但在我必须执行此操作的最后一个项目中,我采用了更简单的方法,最终为 logic_error 和 runtime_error 编写了几个 System.Exception 派生类。然后我会捕获这两个基类并使用 typeid(err) 来编写抛出的 .NET 消息。这样我就不会“丢失”从 C++ 抛出的内容,但不必映射除最重要的部分之外的所有内容。
【讨论】:
一对一映射对我来说似乎是最明智的方法。由于特定于应用程序的异常,“通用”映射几乎是不可能的,尽管 STL 异常类有一些明显的映射。
还有一个来自非托管代码的 SEH 异常问题。根据您的情况,可能还需要捕获和包装它们。
【讨论】:
我认为这取决于包装器的设计。如果管理器包装器的接口与非托管库的接口几乎相同,则以 1:1 的比例重新抛出异常。如果您要显着更改接口,则抛出最适合新接口的异常。无论哪种方式,请确保包装器在任何操作无法完成时抛出异常以符合 .NET 设计准则。
【讨论】:
你真正想做什么?
Interop 已将本机异常转换为托管异常,包括 SEH 异常。然而,良好的设计要求应该在原生 API 级别捕获ALL 异常。除非有充分的理由,否则您不应该偏离这一点。我们对您的设计知之甚少。
【讨论】: