C# 处理异常的方法

C# 处理异常的方法,c#,exception,exception-handling,C#,Exception,Exception Handling,除了日志记录之外,什么构成了异常处理?我的要求就像人们说的,只有抓住一个你能处理的异常 例如,我编写了一个与Active Directory交互的工具。我在域控制器上运行它。由于我对广告非常了解,我可以处理一个例外情况(例如我可以提出要求另一个域名的提示)并从那里开始。但是,如果生产服务器上的域出现如此严重的问题,这不是例外吗 因此,在这种情况下,环境问题应该是异常的(考虑到生产和广告等),但这是我可以处理的。我认为处理异常取决于节目观众(同意) 无论如何,主要的问题是:要推断我是否能够“处理”

除了日志记录之外,什么构成了异常处理?我的要求就像人们说的,只有抓住一个你能处理的异常

例如,我编写了一个与Active Directory交互的工具。我在域控制器上运行它。由于我对广告非常了解,我可以处理一个例外情况(例如我可以提出要求另一个域名的提示)并从那里开始。但是,如果生产服务器上的域出现如此严重的问题,这不是例外吗

因此,在这种情况下,环境问题应该是异常的(考虑到生产和广告等),但这是我可以处理的。我认为处理异常取决于节目观众(同意)

无论如何,主要的问题是:要推断我是否能够“处理”异常,我需要知道需要什么样的处理——而不是记录日志并向用户提供另一个选择(在这种情况下,我使用if file exists等来避免异常)

对于上述案例(AD),我的代码结构如下:

if (adIsAvailable)
  // do whatever here

else
  raise exception and ask for action
这将在gui中捕获

关于这个设计的有效性有什么想法吗?

好问题。 请记住,您只能处理特定类型的异常,并将真正关键的异常传播到堆栈中并被遗忘

异常处理的一种用法是与用户交互,当然,正如您所说,最好的方法是检查一个前提条件,即如果违反(文件不存在)将抛出异常,而不是执行实际任务并依赖异常机制进行通知

异常处理的另一个用法是重试。例如,您正在向数据库发送查询,并收到TimeOutException或另一个指示连接暂时不可用的错误。在这种情况下,您可能需要稍等,然后再试一次。并且,只有当您在(比如)3次之后未能到达Db时,才将异常传播到上层

处理异常的另一种方法是向异常添加数据或更改其类型。 您可能希望捕获TimeOutException,但抛出一个MyApplicationException,其中包含您尝试执行的SQL(原始异常是内部异常)

此外,出于安全原因,您可能希望执行相反的操作—从异常(如堆栈跟踪)中删除数据(向恶意用户公开应用程序的内部工作是不明智的)

顺便说一下,在您的情况下,您可能希望格式化一条用户友好的消息,清楚地说明问题的性质,而不是向用户显示堆栈跟踪和一条模糊的消息。这是在异常处理期间可以完成的转换的另一个示例


不久前,我的应用程序抛出了一个异常,该异常是由于DML操作中的表空间不足引起的。用户收到一个可怕的异常,错误代码为。我所做的是添加一个处理程序,该处理程序检查调用命令时抛出的异常,并为该错误代码添加了特殊处理—它现在可以准确地告诉用户问题出在哪里

这里有几个不同的问题

  • 如何处理(并决定何时处理)底层代码引发的异常
  • 什么时候自己抛出异常
  • 生产代码是否应以不同于开发代码的方式处理“异常”情况
  • 关于第(1)点:

    这可能有点混乱,也很难决定——不同的API可能会以不同的方式使用异常,即使在同一种语言中也是如此

    例如,在C#中,如果我预期输入可能无法解析,我更喜欢使用
    int.TryParse()
    而不是
    int.Parse()
    并捕获
    FormatException
    ,我想编写代码来处理这种情况

    如果我不想处理错误的输入,我将使用
    int.Parse()
    ,并让异常传播

    唉,这要视情况而定

    关于第(2)点:

    例外基本上是指“我放弃”。他们的意思是出了问题,但你不能自己处理

    关于第(3)点:

    我认为这几乎总是个坏主意

    旁白:

    我不同意其中的一部分,它说:

    最好的方法是检查一个先决条件,如果违反了这个先决条件(文件 不存在)将引发异常,而不是执行实际的 任务,并依赖异常机制进行通知

    如果您编写如下代码:

    if (file_exists(x))
    { /* do something */ }
    else
    { /* whatever */ }
    
    然后,你要向比赛条件敞开心扉。 可能该文件在
    文件\u exists()
    检查之间被删除,因此您的代码仍将抛出异常

    或者该文件是在您进入
    else
    部分后创建的


    在这种情况下,我认为最好做您正试图做的事情,如果出现问题,请处理异常。

    如果
    !adIsAvailable
    意味着它甚至找不到域服务器,我认为这是一种例外情况。如果它找不到你要找的搜索结果,我不会叫它Exception.fyi自动重试,请极端小心@我完全同意,重试应该谨慎使用,最好是在应用程序的最低级别。e、 很好的回答,我不认为重试是一种机制,因为前面的评论中有链接。不过,在某些情况下,重试可能是可行的。为了构造代码,我可以在循环中尝试一个操作,如果成功则退出,如果重试尝试=3,则在循环中执行检查,如果是,则抛出一个异常。但是在文件打开示例中,您需要包装一个try catch来捕获竞争条件,然后处理它?这是一个经典的例子。@dotnetdev:使用try-catch,没有竞争条件,也不需要事先检查任何东西。要么文件已打开