区分相同类型的异常

7
什么是区分相同类型但因不同原因而抛出的两个异常之间的最佳方法?
例如,当尝试访问空序列时,可能会抛出InvalidOperationException,但在使用Concurrent对象(例如BlockingCollection)时也可能抛出。
根据我的阅读,我得出结论:使用BlockingCollection.CompleteAdding()来表示完成是完全可以的,因此需要捕获异常并适当处理(例如退出任务)。
在不使用消息内容的情况下,最好的过滤方法是什么?
编辑:它们似乎具有相同的HResult值。

1
你有检查过他们的 InnerException 吗? - Ghasem
4
您可以使用非常具体的范围立即捕获它并重新抛出自定义异常,否则您将不得不依赖错误消息。尽管C#6使这个过程稍微好一些:http://druss.co/2015/05/c-6-0-exception-filters-try-catch-when/ - Rob
@Alex 我会仔细检查是否有 InnerException。这可能是某些情况下的选项,但并不是真正的解决方案。 - galford13x
@Rob 像我想的一样。谢谢你提供的链接,那是有趣的消息。 - galford13x
4
为什么这很重要?如果您能够处理生成异常的案例,那么它就永远不会被抛出。因此,即使您能够区分它们,又有何帮助呢? - jgauffin
3个回答

1
据我所知,您只能通过Message来区分两个相同TypeException

然而,您不应该依赖Message来做Catch决策。根据执行代码的系统的语言环境配置,Message可能会被本地化。如果系统的语言与您硬编码的Message的语言不同,则会使您的Catch When块不相关。

唯一可以使用Message的情况是当您是系统管理员并编写服务器软件时,您确定您使用的语言将来不会更改(当您编写要在客户端设备上运行的软件时不能保证这一点)。


0
这是一个不稳定的解决方案(因为.NET的源代码可能会在未来发生变化),但我找不到其他的解决方案。

例如,如果你想要检测带有以下信息的InvalidOperationException
"只有在完成状态(RanToCompletion、Faulted或Canceled)下,才能释放任务。"
...,那么你可以使用以下代码:
try
{
    ...
}
catch (Exception exc)
{
    string taskErrMsg = null;
    if (exc is InvalidOperationException)
    {
        try
        {
            Assembly sysAsm = Assembly.GetAssembly(typeof(System.String)); // get System assembly
            System.Resources.ResourceManager rm = new("System.Private.CoreLib.Strings", sysAsm);
            taskErrMsg = rm.GetString("Task_Dispose_NotCompleted"); // get the error message in the current language
        }
        catch { }
    }
    if (taskErrMsg is not null && exc.Message == taskErrMsg)
    {
        // if the exception is related to task disposal
    }
    else
    {
       ...
    }
}

我通过查看这里的`Task`类的源代码(https://source.dot.net/#System.Private.CoreLib/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/Task.cs,29d432e77814898d)提出了这个解决方案。

你可以在这里查找其他的消息ID - https://source.dot.net/#System.Private.CoreLib/artifacts/obj/coreclr/System.Private.CoreLib/x64/Debug/System.SR.cs,594002b480c91cd7

尝试将这些添加为链接,但似乎代码块破坏了下面的所有文本突出显示。

0

我曾经遇到过类似的问题,即无法捕获同一类型的异常,因为它们是在我无法访问的代码片段中抛出的。我的解决方案是通过异常的源和目标站点进行区分。这种方法有点像“临时修补”,但它确实有效。


这并没有回答问题。一旦您有足够的声望,您就能够评论任何帖子;相反,提供不需要询问者澄清的答案。- 来自审核 - Alberto

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接