C#中的3个catch块变体之间有什么区别('Catch','Catch(Exception)'和'Catch(Exception e)')?

时间:2013-06-12 19:37:06

标签: c# visual-studio-2010 exception try-catch

在C#中,'Catch','Catch(Exception)'和'Catch(Exception e)'之间有什么区别?

MSDN article on try-catch在其示例中使用了其中的2个,但没有解释使用目的的差异。

try
{}
catch 
{}

try 
{}
catch (Exception)
{}

try
{}
catch(Exception e)
{}

这些有何不同?哪些会捕获所有异常,哪些会捕获特定异常?

7 个答案:

答案 0 :(得分:45)

还没有人提到这个问题的历史方面。

在.NET中,抛出一个不是从Exception派生的对象是合法的。 (它在C#中不合法,但它在其他一些托管语言中。)许多人不知道这个事实,但它是合法的。由于这是 crazy ,在.NET 2.0中默认值已更改:如果您尝试抛出非异常的内容,则它会自动封装在RuntimeWrappedException类中,显然 是一个例外。然后扔掉那个对象。

由于这种奇怪之处,在C#1.0中,通常看到代码同时执行:

try
{ do something }
catch(Exception) 
{ handle the exception }
catch
{ handle the thrown non-exception }

事实上,存在安全性和正确性问题;在某些情况下,出于安全原因,您必须捕获任何被抛出的东西(可能会重新抛出它),人们会合理地认为catch(Exception)抓住了所有东西,但事实并非如此。

幸运的是,自从.NET 2.0以来,事情变得更加明智;如果需要,您可以依靠catch {}catch(Exception) {}catch(Exception ex) {}来抓取所有内容。

最后:如果出于某种疯狂的原因你想要打开C#1.0行为,你可以把

[assembly:System.Runtime.CompilerServices.RuntimeCompatibility(WrapNonExceptionThrows = false)]

在您的计划中。

答案 1 :(得分:23)

简而言之......

没有参数的

Catch将收到任何异常,但无法解决此问题。

Catch (Exception)基本上会做同样的事情,因为你已经指定了根Exception类型。而Catch (IOException)只会捕获IOException类型。

Catch (Exception ex)捕获所有异常,并通过ex变量提供解决方法。

了解详情:http://msdn.microsoft.com/en-us/library/ms173160.aspx

答案 2 :(得分:9)

第一个版本捕获从Exception类派生的所有异常。

第二个版本捕获指定的异常。

第三个版本捕获具有声明名称的指定异常。然后在catch块中,您可以使用此对象,例如,查看完整错误:e.ToString();

了解更多here

答案 3 :(得分:6)

所有这些基本上都是相同的,不同之处在于它们提供的有关错误的信息量。

catch (foo ex) {}将过滤掉所有异常,但可以转换为foo类型的异常除外。它还为您提供了错误的实例。

catch (foo) {}执行与上面相同的操作,但它不会为您提供异常的实例。您将知道异常的类型,但无法从中读取信息。

请注意,在这两种情况下,如果异常类型为Exception,它们将捕获所有异常。

catch {}捕获所有异常。您不知道它捕获的类型,也无法访问该实例。

您可以根据捕获异常所需的信息来选择使用哪一个。

无论您使用哪一个,都可以使用命令throw;(不带参数)向前传递捕获的异常。

答案 4 :(得分:3)

在您的示例中,没有任何内容,因为您没有对异常做任何事情。但要澄清......

  • 这会抓住所有内容,但除了例外之外什么都不做。

    catch {}
    

    仅当您想要保证从方法返回时才有用。

  • 这只捕获Exception类型的异常(这就是所有内容),但不会对异常做任何处理。

    catch (Exception) {}
    

    如果要通过指定要处理的类型来限制捕获的异常类型,这非常有用。任何其他异常都会冒出调用堆栈,直到找到合适的处理程序。

  • 这只捕获Exception类型的异常(这就是所有内容),并且可以对异常执行某些操作,但不会执行任何操作

    catch (Exception ex) {}
    

    这项技术为您提供了更多选择。您可以记录异常,检查InnerException等。再次,您可以指定要处理的异常类型。

除非你以某种方式重新抛出异常,否则所有这些都是不好的做法。一般来说,你应该只捕捉你可以有意义地处理的例外,并允许其他任何事情冒泡。

答案 5 :(得分:1)

添加catch(Exception e)将允许您访问Exception对象,该对象包含有关抛出的异常的详细信息,例如Message和StackTrace;记录此信息以帮助诊断错误很有用。如果没有声明您尝试捕获的异常,那么一个简单的catch就不会让您访问异常对象。

此外,捕获基本异常通常被认为是不好的做法,因为它过于通用,并且在可能的情况下,您应该首先考虑特定的异常。例如,如果您正在使用文件,则可以考虑以下try / catch块:

try{
    //open your file and read/write from it here
}catch(FileNotFoundException fe){
    //log the message
    Log(fe.Message);
}catch(Exception e){
    //you can catch a general exception at the end if you must
}finally{
    //close your file
}

答案 6 :(得分:1)

在最高级别,他们都是一样的;他们都抓住了例外。

但是要进一步向下钻取,在第一种情况下,您正在捕获异常并且不执行任何操作(您没有定义的类型)。在第二个示例中,您将捕获异常类型的异常。在上一个示例中,您将捕获与示例2中相同的异常类型,但现在您将异常放入一个允许您在MessageBox中显示它的变量或:

e.Message

重要的是要注意异常是分层意义,如果你在同一个try / catch块中捕获多种类型的异常,你会从最具体的异常类型转到最常见的异常类型。像这样:

try {
}
catch (SqlException sqlExc) {
}
catch (Exception exc) {
}