【问题标题】:C# Exception Catching using try..catch blocks使用 try..catch 块进行 C# 异常捕获
【发布时间】:2011-10-06 05:25:12
【问题描述】:

我是 C# 新手,想更好地了解异常捕获。这些问题可能是愚蠢的菜鸟问题。它们对我很重要,我提前道歉。

例如,在 System.IO Path 类 GetFullPath 中,可以抛出五个异常:ArgumentException、SecurityException、ArgumentNullException、NotSupportedException 和 PathTooLongException。我知道必须组织 catch 块,以便首先捕获最具体的异常,最后捕获最一般的异常。

问题 1: 当 MSDN 提供有关类可能引发的异常的信息时,我如何知道哪个异常是最具体的,哪个是最不具体的?换句话说,我如何从 MSDN 给我的内容中确定从最具体到最不具体的异常顺序?

问题 2: 我是否需要明确地明确捕获所有异常,还是只使用最一般的异常来捕获所有其他异常?比如还是用Path类,是不是需要做...

try { ... }
catch(System.ArgumentNullException ane) { ... }
catch(System.NotSupportedException nse) { ... }
catch(System.IO.PathTooLongException ple) { ... }
catch(System.IO.SecurityException se) { ... }
catch(System.ArgumentException ae) { ... }

或者将是一个简单的...

catch(System.ArgumentException ae) { ... }

捕获所有异常?

问题 3: 在 bool 方法中执行以下操作是否正确的语法结构...

try
{
  ... ;
  return true;
}
catch(System.ArgumentException ae)
{
  ... ;
  return false;
}

【问题讨论】:

  • 答案是:除非您知道自己能处理好(也就是说,除非您能真正修复问题),否则不要抓住它们。这个问题是重复的,我会尝试找到它重复的问题。
  • 谢谢。我只需要为了从 bool 方法返回 false 来捕获它们。谢谢你的链接。我会看看他们。
  • 如果你只想捕获所有并返回 false 只捕获 System.Exception 基类,甚至只使用 catch { return false; }

标签: c# exception-handling try-catch block


【解决方案1】:

问题 1

在每个异常的 MSDN 文档中,您可以看到它的继承链。这会告诉您哪些更具体(在链条的下游,它们更具体)。

您还可以在 Visual Studio 对象浏览器中查看此信息。

问题 2

捕捉异常是一种很好的做法,你可以做一些事情。如果你不能合理地处理这个例外,那就让它冒泡吧。

一般来说,tt最好先捕获更具体的异常。

您还需要查看不同的继承链并决定要捕获哪些异常。例如,只是做:

catch(System.ArgumentException ae) { ... }

不会捕获 System.IO.SecurityException,因为 System.IO.SecurityException 不继承自 System.ArgumentException

问题 3

是的,这是有效的语法。

我不会说好的做法。如果这是异常情况,最好让异常冒泡。建议的设计将导致异常被忽略,并且针对此方法进行编程的任何人都需要检查返回值(他们可能会忘记)。

【讨论】:

  • 谢谢。关于问题 2,就我而言,所有例外情况都应允许用户更正其输入。我不想重复努力,因此需要一个捕获块来捕获它们。
  • 关于问题1,对于ArgumentException,继承层次结构是... System.Object System.Exception System.SystemException System.ArgumentException More... 但是对于SecurityException 它是... System.Object System .Exception System.SystemException System.Security.SecurityException,那我怎么知道哪个更具体?
  • @Zeos6 - 将捕获上述所有异常的基本异常类是Exception。但是,这很危险,因为它还会捕获OutOfMemoryException 之类的东西。最好处理几个具有特定异常的 catch 块(并且可能都调用一个公共函数)。
  • @Zeos6 - 关于问题 1,去 MSDN 上查看。
  • 啊……灯泡时刻!所以使用 Catch(Exception ex) { ... } 将捕获它们,因为它是所有它们的基类。正确的?我明白了......假设我在这里是正确的。
【解决方案2】:

一些准则:

  1. 您可以通过查看 MSDN 上异常的继承层次结构来判断异常的“特异性”。如果它们派生自公共基类,则基类异常不太具体。一个常见的例子是 IOException,它是几个与 I/O 相关的更具体异常的基类。

  2. 您通常不应该捕获使用异常,如 ArgumentException、ArgumentNullException、NotSupportedException 等。如果抛出这些异常,它们表明您的代码中存在必须修复的错误。这些只能由您的“最终捕获”捕获以记录并可能在关闭应用程序之前格式化错误以便更友好地显示。


回应评论:

在验证输入后捕获使用异常是一个坏习惯,特别是如果通过捕获Exception 来完成(因为这可以掩盖其他意外异常类型。)提前验证要好得多。不幸的是,这个特定的方法 (Path.GetFullPath) 没有很好地考虑这些准则,因此您需要处理 ArgumentException、NotSupportedException 和 PathTooLongException 来验证用户输入。您可以像这样在单个 catch 子句中执行此操作:

try
{
     //Call Path.GetFullPath somewhere in here
}
catch (Exception ex)
{
     if (ex is ArgumentException || ex is NotSupportedException || ex is PathTooLongException)
     {
          //Your handling here
     }
     else
     {
          throw;
     }
}

您希望尽量缩短 try 块内的代码,因为您不想无意中抑制 Path.GetFullPath 可能引发的其他使用异常。但是,您实际上可能希望单独处理每个异常,因为您可以使用它们之间的差异向用户提供有用的反馈,说明他们做错了什么。

【讨论】:

  • 谢谢。不幸的是,我不太明白如何执行您在 1 中的建议。关于第 2 项,我正在尝试验证路径并捕获这些异常允许我放置一个文本框以允许用户更正他们的输入。所以,我需要抓住他们。问题是我是否可以使用一次捕获来捕获所有这些。
【解决方案3】:
  1. 当您将异常名称指定为 catch(System.ArgumentNullExcpetion) 时,它将仅捕获那些类型。您可以在 msdn 上的异常文档页面上查看继承描述,以检查更通用的异常,您只需要担心这些。

  2. 您可以捕获最普遍的异常,但有时特定的异常在您编写和调试程序时可能会更有用,它可能会帮助您了解引发的异常类型。

    李>
  3. 是的,可以使用该语法。

【讨论】:

  • 谢谢。我现在明白了。在我的例子中,所有的异常都来自用户的错误输入,所以我想给他们一个机会来修改他们的输入并重新提交,而不是从头开始。
  • 是的,就像每个人都说的那样,在这种情况下,您可以找到Exception
【解决方案4】:

1) 大多数情况下,您可以通过名称来判断。 (例如,ArgumentNullException 继承自 ArgumentException)。当您无法通过名称判断时,您可以查看文档或对象浏览器,它应该会为您提供继承树。

2) 具体捕获哪些将取决于您的需求。许多人会告诉你,即使得到 ArgumentException 或 ArgumentNullException 意味着作为开发人员的你未能在调用中验证更高级别的内容。

3) 如果您遇到异常,您通常不想返回任何内容 - 异常本身意味着您的方法未能正确完成,这意味着您无论如何都无法为您的返回值提供好的数据。不过也有例外,所以 YMMV。

【讨论】:

  • 我要感谢你们所有人,你们的时间和知识非常乐于助人和慷慨。谢谢你。所有答案对我来说都是适用且有价值的,但我不知道如何将此问题标记为已回答,并将所有条目作为答案。
【解决方案5】:

1) 任何异常的特定性都基于其从更通用的基类异常的继承层次结构。

2) 您可以使用如下一般捕获:

try
{
    ...
}
catch (System.Exception ex)
{
    ...
}

3) 是的,这很好,尽管在您已经拥有更具体的ArgumentException 之后,您可能希望在我的 (2) 答案中显示全部内容。

【讨论】:

  • 我已经抓住了这个克里斯,使用 ... if(null == input || 0 == input.Length)
  • 在任何更具体的异常处理程序结束时捕获所有异常总是值得的。
  • 谢谢。我会采用这种做法。
猜你喜欢
  • 1970-01-01
  • 2015-06-26
  • 2013-12-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-06
相关资源
最近更新 更多