catch(Exception)、catch()和仅使用catch之间的区别

19
我想知道是否能够安全地编写一个只捕获所有System.Exception类型的catch()。还是说我必须坚持使用catch(Exception)来完成这个任务。我知道对于其他异常类型(例如InvalidCastException),我必须指定类型,如catch(InvalidCastException)。换句话说,我想问以下代码示例是否相同。

这...


可以这样写:
catch (Exception e) { // catch all System.Exception types }
也可以这样写:
catch () { // catch all System.Exception types }
两者都是一样的。
try
{
    //do something
}
catch(Exception)
{
    //handle exception
}

这段代码意味着在HTML文档中有一个段落元素。段落元素通常用于显示一段文本,浏览器会在文本的前后添加空白以分隔段落。

try
{
    //do something
}
catch() //Causes compile time error "A class type expected"
{
    //handle exception
}

并且这个...

try
{
    //do something
}
catch
{
    //handle exception
}

更新:我的问题有误。catch()在c#中是不允许的。


1
是的,它们都是相同的,但对于C#.NET来说并非如此。 - Shankar Narayana Damodaran
1
是的,所有这些都是一样的。无论你怎么写,这都是一个不好的想法。你应该只捕获那些你准备好处理的异常。无条件地捕获所有异常并不是我所谓的“干净代码”。 - Jim Mischel
1
你计划在catch块内部做什么?你认为“处理”异常是什么意思?你提供的三个示例都无法访问异常本身,因此很难想象如何有用地“处理”它。 - John Saunders
1
在C#.net中,你必须专门指定catch(Exception)catch(NullReferenceException)(如果你知道异常)。在C#.net中,你不能让catch块为空,像这样catch(),Intellisense会显示错误。 - Shankar Narayana Damodaran
1
@CleanCoder:根据你的项目,你可能根本不应该“处理”异常。 - John Saunders
显示剩余5条评论
5个回答

16
在完美的世界中,您不应该使用 catch(Exception) 或者单独使用 catch,因为您永远不应该捕获通用的 Exception 异常。您总是应该捕获更具体的异常(例如 InvalidOperationException 等)。
在现实世界中,catch(Exception) 和单独使用 catch 是等效的。我建议仅在您打算仅重用异常变量时使用 catch(Exception ex),而在其他情况下仅使用 catch(单独)。对于第二个用例,这只是一个风格问题,但我个人认为这样更简单。
真正重要的是(即使超出了您问题的范围),您永远不要编写以下代码:
try
{
}
catch (SpecificException ex)
{
    throw ex;
}

这会将堆栈跟踪重置为抛出点。另一方面:

try
{
}
catch (SpecificException)
{
    throw;
}

保留原始堆栈跟踪信息。


8

这两种结构(正如sh4nx0r所指出的catch ()是语法错误)在C#中的表现相同。允许它们的事实可能是从C++语法继承下来的。

其他语言,包括C++/CLI,可以抛出不派生自System.Exception的对象。在这些语言中,catch将处理这些非CLS异常,但catch(Exception)则不会。


请看上面sh4nx0r的评论,C#中不允许使用catch()语句,否则会抛出编译错误"A class type expected"。 - CleanCoder
@CleanCoder,你说得对,我确实过多考虑了其他语言。回答已相应更新,感谢提醒 :) - Frédéric Hamidi

3
catch(Exception ex)可以处理所有派生自System.Exception类的异常,但如果抛出的异常不是派生自System.Exception,那么它将无法被catch(Exception ex)处理。
在.NET 3.0之前,由不安全代码引发的异常(即未针对CLR的代码)由catch{}处理。在.NET Framework 3.0之后,所有类型的异常都可以由System.Exception类处理。现在catch{}已经过时。

1

-1
如果发生异常意味着您需要运行一段代码,但是如果您捕获了异常却不会对其进行任何操作,除非重新抛出它,否则最好的方法可能不是捕获异常,而是执行以下操作:
  bool ok=false;
  try
  {
    ... 做一些事情--请参阅下面关于“返回”的注释
    ok = true;
  }
  finally
  {
    if (!ok)
    {
      ... 在此处清理代码
    }
  }
这种模式的一个弱点是必须在try块内的任何return语句之前手动添加ok = true;(并确保没有其他异常(也许ThreadAbortException除外)可以在ok = true;和return之间发生)。 否则,如果您不打算对异常进行任何操作,则不应该捕获它。

-1,Catch()实际上非常有用。如果我正在更新10条记录,其中一条记录抛出无效日期的异常。如果我不使用catch,那么在该异常之后的所有记录都将无法更新。如果我使用catch,我可以简单地识别该错误并向用户显示它,同时更新其余记录。 - TheTechGuy
你对异常怎么处理?是要舍弃它还是存储以备后用?我想应该是这样的。我建议用我的代码替代那种在catch块内无条件参数重抛的模式。但这不适用于catch块不会重抛的情况。 - supercat
不,我认为你错了。你是说,你只是在捕获异常后重新抛出它?那是错误的。你要捕获异常,以友好的方式向用户展示它,然后程序的其余部分就可以正常执行。我为什么要存储我的异常? - TheTechGuy
@Thecrocodilehunter:我的观点是,我给出的“try/finally”代码是在一个否则会使用catch(Exception ex) {...do something...; throw;}的场景中的一种改进的替代方案,这是我经常见到的一种模式。对于您描述的情况,人们不会使用后者模式,因此我的前者模式不应被视为替代品。 - supercat

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接