两者有什么区别

try { ... }
catch{ throw }

and

try{ ... }
catch(Exception e) {throw new Exception(e.message) }

不管第二个显示的是一条消息。


当前回答

第一个保存原始的stacktrace:

try { ... }
catch
{
    // Do something.
    throw;
}

第二个选项允许您更改异常和/或消息和其他数据的类型:

try { ... } catch (Exception e)
{
    throw new BarException("Something broke!");
}

还有第三种传递内部异常的方法:

try { ... }
catch (FooException e) {
    throw new BarException("foo", e);
} 

我建议使用:

如果您想在错误情况下做一些清理,而不破坏信息或添加关于错误的信息,则使用第一种方法。 如果您想添加关于错误的更多信息,则使用第三个。 如果您想隐藏信息(不受信任的用户),则使用第二种方法。

其他回答

第一个保存原始的stacktrace:

try { ... }
catch
{
    // Do something.
    throw;
}

第二个选项允许您更改异常和/或消息和其他数据的类型:

try { ... } catch (Exception e)
{
    throw new BarException("Something broke!");
}

还有第三种传递内部异常的方法:

try { ... }
catch (FooException e) {
    throw new BarException("foo", e);
} 

我建议使用:

如果您想在错误情况下做一些清理,而不破坏信息或添加关于错误的信息,则使用第一种方法。 如果您想添加关于错误的更多信息,则使用第三个。 如果您想隐藏信息(不受信任的用户),则使用第二种方法。

扔;重新抛出原始异常并保留其原始堆栈跟踪。

把交货;抛出原始异常,但重置堆栈跟踪,在catch块之前销毁所有堆栈跟踪信息。


永远不要写throw ex;


抛出新的异常(ex.Message);更糟糕。它创建了一个全新的Exception实例,丢失了异常的原始堆栈跟踪及其类型。(例如,IOException)。 此外,一些异常包含额外的信息(例如,ArgumentException.ParamName)。 抛出新的异常(ex.Message);也会毁掉这些信息。

在某些情况下,您可能希望将所有异常包装在自定义异常对象中,以便您可以提供有关抛出异常时代码正在做什么的附加信息。

为此,定义一个继承Exception的新类,添加所有四个异常构造函数,并可选地添加一个额外的构造函数,该构造函数接受一个InnerException以及其他信息,并抛出您的新异常类,将ex作为InnerException参数传递。通过传递原始的InnerException,可以保留所有原始异常的属性,包括堆栈跟踪。

第二个示例将重置异常的堆栈跟踪。第一个最准确地保留了异常的起源。

此外,您还打开了原始类型,这是了解实际出错的关键……如果第二个属性是功能所必需的——例如,添加扩展信息或用特殊类型(如自定义的'HandleableException')重新包装,那么只需确保InnerException属性也设置了!

还有一点我没看到有人说:

如果你没有在catch{}块中做任何事情,尝试一下…捕捉是没有意义的。我经常看到这样的情况:

try 
{
  //Code here
}
catch
{
    throw;
}

或者更糟:

try 
{
  //Code here
}
catch(Exception ex)
{
    throw ex;
}

坏的:

try 
{
  //Code here
}
catch(Exception ex)
{
    throw new System.Exception(ex.Message);
}

最重要的区别是第二个表达式删除了异常的类型。异常类型在捕获异常方面起着至关重要的作用:

public void MyMethod ()
{
    // both can throw IOException
    try { foo(); } catch { throw; }
    try { bar(); } catch(E) {throw new Exception(E.message); }
}

(...)

try {
    MyMethod ();
} catch (IOException ex) {
    Console.WriteLine ("Error with I/O"); // [1]
} catch (Exception ex) {
    Console.WriteLine ("Other error");    // [2]
}

如果foo()抛出IOException,[1]捕获块将捕获异常。但是当bar()抛出IOException时,它将被转换为普通异常,并且不会被[1]捕获块捕获。