在C#中,'Catch','Catch(Exception)'和'Catch(Exception e)'之间有什么区别?
MSDN article on try-catch在其示例中使用了其中的2个,但没有解释使用目的的差异。
try
{}
catch
{}
try
{}
catch (Exception)
{}
try
{}
catch(Exception e)
{}
这些有何不同?哪些会捕获所有异常,哪些会捕获特定异常?
答案 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
变量提供解决方法。
答案 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) {
}