try
{}
catch
{}
try
{}
catch (Exception)
{}
try
{}
catch(Exception e)
{}
这些有什么不同?哪些可以捕获所有异常,哪些只能捕获特定的异常?
try
{}
catch
{}
try
{}
catch (Exception)
{}
try
{}
catch(Exception e)
{}
目前还没有人提到这个问题的历史方面。
在.NET中,抛出一个不派生自Exception
的对象是合法的。(在C#中是不合法的,但在一些其他托管语言中是合法的。)许多人不知道这个事实,但它是合法的。由于这很疯狂,所以在.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)]
在你的程序中。
Catch
语句可以捕获任何异常,但不能提供解决方法。
Catch (Exception)
语句本质上与前者相同,因为您已经指定了根Exception
类型。 而Catch (IOException)
语句只会捕获IOException
类型的异常。
Catch (Exception ex)
语句可以捕获所有异常,并通过变量ex
提供一种解决方法。第一个版本捕获所有从Exception类派生的异常。
第二个版本捕获指定的异常。
第三个版本使用声明名称捕获指定的异常。然后在catch块中,您可以使用此对象,例如查看完整的错误:e.ToString();
阅读更多信息这里。
e.Message
。 - DonBoitnottException
类型或任何派生自Exception
的内容。 - Adam Houldsworthcatch (foo ex) {}
将过滤掉所有异常,除了那些可以转换为类型 foo
的异常。它还会为您提供错误实例以便处理。
catch (foo) {}
与上面的语句相同,但不会为您提供异常实例。您将知道异常类型,但无法从中读取信息。Exception
,它们将捕获所有异常。
catch {}
捕获所有异常。您不知道它捕获的类型,并且无法访问实例。throw;
(不带参数)将捕获的异常传递给后续处理语句。This catches everything but does nothing with the exception.
catch {}
This is only useful when you want to say guarantee a return from a method.
This catches only exceptions of type Exception
(which is everything) but does nothing with the exception.
catch (Exception) {}
This is useful if you wanted to limit the type of exception being caught by specifying which types you want to handle. Any other exceptions will bubble up the call stack until a proper handler is found.
This catches only exceptions of type Exception
(which is everything) and could do something with the exception, but happens to do nothing
catch (Exception ex) {}
This technique gives you a lot more options. You could log the exception, inspect the InnerException
, etc. And again you can specify which types of exceptions you wish to handle.
除非你要重新抛出异常,否则所有这些做法都是不好的。通常来讲,你只应该捕获你可以有意义地处理的异常,并且允许其他任何异常继续传递。
catch
将要处理的每个类型的另一个catch
块后面再出现catch
块。但是,它允许catch (Exception) { ... } catch { ... }
,其中最后一个块可能无法到达。根据这个答案,除了C#之外的一些语言可能会"throw"一个不是System.Exception
的对象。这是真的吗?我听说在这种情况下,异类对象最终仍将由运行时包装在Exception
中,但这是否正确? - Jeppe Stig Nielsentry{
//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
}
在最高层面上,它们都是相同的;它们都捕获异常。
但是如果进一步深入,第一个例子中,您捕获了一个异常并且没有做任何处理(您没有定义类型)。在第二个例子中,您捕获了 Exception 类型的异常。在您最后的例子中,您捕获了和示例2中相同的 Exception 类型,但现在您将异常放入一个变量中,这样您可以在 MessageBox 或其他地方显示它:
e.Message
需要注意的是,异常是分层的。这意味着,如果你在同一个try/catch块中捕获多种类型的异常,你应该从最具体的异常类型到最一般的异常类型进行处理。就像这样:
try {
}
catch (SqlException sqlExc) {
}
catch (Exception exc) {
}