C# 为什么要创建自定义异常?

C# 为什么要创建自定义异常?,c#,.net,exception,C#,.net,Exception,为什么我们需要在.NET中创建自定义异常?我不确定“技术上”为什么,但假设我有一个使用权限的应用程序/网站。如果某人没有正确的权限,抛出DivideByZero异常或IOException有点愚蠢。相反,我可以创建AccessDeniedException,这将帮助我以后进行调试。因此,您也可以自己抛出它们,然后捕获它们并确切了解它们的含义 另外:如果您正在构建类库/框架/api,那么创建代码中其他异常继承自的BaseException通常很有用。然后,当您的代码引发异常时,使用它的程序员可以很

为什么我们需要在
.NET中创建自定义异常?

我不确定“技术上”为什么,但假设我有一个使用权限的应用程序/网站。如果某人没有正确的权限,抛出DivideByZero异常或IOException有点愚蠢。相反,我可以创建AccessDeniedException,这将帮助我以后进行调试。

因此,您也可以自己抛出它们,然后捕获它们并确切了解它们的含义


另外:如果您正在构建类库/框架/api,那么创建代码中其他异常继承自的BaseException通常很有用。然后,当您的代码引发异常时,使用它的程序员可以很快知道异常的来源。

因为它可以清楚地表明您的意图,并且您还可以使用IDE功能跟踪使用情况。假设您有一个名为“FooBar”的自定义后端系统,并且您创建了一个“FooBarDownException”,您可以跟踪此异常的使用情况,以识别应用程序包含的任何自定义逻辑,因为FooBar已关闭。您可以选择捕获此特定类型的异常并忽略其他异常,从而避免异常处理程序中的重载和条件逻辑。这实际上只是强类型的另一个版本。这还意味着您可以避免在代码中添加注释,因为异常有一个意图透露名称。

这与您为非.NET应用程序创建不同的退出代码的原因相同:指定不同的应用程序特定错误。比如…
connectionbrokernexception
或者嗯…
usersoundsbadexception
之类的


这样你就可以准确地知道哪里出了问题,并采取适当的行动。例如,如果您尝试发送一些数据,而数据传输类抛出了一个
ConnectionBrokernexException
,则可以弹出一个重新连接对话框并尝试重新连接。然后,如果重新连接方法超时,它将抛出一个
ConnectionTimeoutException
,您可以再次正确操作。

标准的.NET异常不会覆盖任何应用程序中可能出错的所有错误,也不打算覆盖它们。除非您的程序非常简单,否则您可能必须创建至少几个自定义异常。

正如Joel所写:因此您也可以自己抛出它们,然后捕获它们并确切了解它们的含义


此外,您可以添加有关该问题的特定信息,以便让异常处理程序能够更准确地执行操作。

最近我在博客上发表了一篇关于该主题的长篇博文:

它的关键在于:只有在下列情况之一为真时才创建自定义异常

  • 你真的希望有人来处理它
  • 您想记录有关特定错误的信息

  • 特定的海关例外允许您为catch语句分离不同的错误类型。异常处理的常见构造如下:

    try
    {}
    catch (Exception ex)
    {}
    
    这将捕获所有异常,无论其类型如何。但是,如果您有自定义异常,则可以为每种类型使用单独的处理程序:

    try
    {}
    catch (CustomException1 ex1)
    {
        //handle CustomException1 type errors here
    }
    catch (CustomException2 ex2)
    {
        //handle CustomException2 type errors here
    }
    catch (Exception ex)
    {
        //handle all other types of exceptions here
    }
    

    因此,特定的异常允许您更好地控制异常处理。这一好处不仅由自定义异常共享,而且由.NET系统库中的所有其他异常类型共享。

    首先,异常是在库中实现的,而不是在语言中实现的——它们如何在库中创建异常?我很确定你不是在提倡系统库应该有一套不同的规则

    另一方面,实际上可以使用异常的对象树。如果愿意,继承的异常可以具有特殊属性——它们可以用于比实际情况更复杂的事情。我不主张将它们用作一般的数据传输机制或任何东西(尽管它们可以),但我可以看到有人实现了一个自定义日志解决方案,该解决方案要求异常上有一个特殊属性

    您的自定义异常可能包含一个指示特殊处理的标志(可能是一个指示您应该重新启动JVM的标志),它们可能包含有关日志记录级别的信息,等等


    不管怎么说,我不是在提倡这种东西,我只是说这是可能的。第一段是你真正的答案。

    如果内置异常恰当地描述了问题/异常,你不应该这样做。我不会创建自己的基类来创建自定义的
    ArgumentException
    ArgumentNullException
    InvalidOperationException

    您可以创建自己的异常,并在更高级别上描述错误。但是,这通常对从使用者类进行调试没有多大帮助


    如果您自己抛出并捕获异常,则可能会出现自定义异常。

    另一个原因是,当客户端与接口对话时。由于客户机不知道接口的实现,并且可能会抛出不同的异常,因此最好创建自定义异常来统一抛出的错误

    我写了一篇关于这个特殊案例的文章:


    我不会说IDE功能是卖点,但最重要的原因是明确自己的意图。我认为,强大的键入功能可以真正使用代码并使其变得更好,这是持续重构的一个促成因素。所以工具很重要。明确意图意味着什么?我可以了解轨迹的使用情况,因为这将发现所有可能由于FooBar关闭而受到影响的区域(在许多不同的情况下使用的标准异常类型,如ArgumentException,不会提供这种好处)。我不喜欢使用
    InvalidOperationException
    (或者,就此而言,大多数框架异常)用于调用方可能尝试处理和恢复的条件。问题是,即使该方法被记录为在某些已知系统状态下抛出一个
    invalidoOperationException
    ,也有可能在内部调用