抛出和抛出新的exception()
有什么区别
try { ... } catch{ throw }
和
try{ ... } catch(Exception e) {throw new Exception(e.message) }
无论第二个显示一个消息?
throw;
重新抛出原始exception并保留其原始堆栈跟踪。
throw ex;
抛出原来的exception,但重置堆栈跟踪,销毁所有的堆栈跟踪信息,直到你的catch
块。
永远不要写出throw ex;
throw new Exception(ex.Message);
更糟。 它创build一个全新的Exception
实例,失去原来的exception的堆栈跟踪,以及它的types。 (例如, IOException
)。
另外,一些exception保存附加信息(例如, ArgumentException.ParamName
)。
throw new Exception(ex.Message);
也会破坏这个信息。
在某些情况下,您可能希望将所有exception包装在自定义exception对象中,以便您可以提供有关在抛出exception时代码执行的其他信息。
为此,定义一个inheritanceException
的新类, 添加所有四个exception构造函数 ,还可以select一个额外的构造函数,该构造函数接受InnerException
以及附加信息,并抛出新的exception类, 并将ex
作为InnerException
parameter passing 。 通过传递原始的InnerException
,可以保留原始exception的所有属性,包括堆栈跟踪。
第一个保留原始堆栈跟踪:
try { ... } catch { // Do something. throw; }
第二个允许您更改exception和/或消息和其他数据的types:
try { ... } catch (Exception e) { throw new BarException("Something broke!"); }
还有第三种方法可以传递内部exception:
try { ... } catch (FooException e) { throw new BarException("foo", e); }
我build议使用:
- 第一个如果你想在错误的情况下做一些清理而不破坏信息或添加有关错误的信息。
- 第三,如果你想添加更多关于错误的信息。
- 第二,如果你想隐藏信息(来自不受信任的用户)。
throw
重新抛出捕获的exception,保留堆栈跟踪,而throw new Exception
失去了一些捕获exception的细节。
通常你会使用throw
来logging一个exception,而不是在那个时候完全处理它。
BlackWasp有一篇很好的文章,标题为“ 在C#中抛出exception” 。
抛出一个新的exception就会吹走当前的堆栈跟踪。
throw;
将保留原始的堆栈跟踪,并且几乎总是更有用。 该规则的例外情况是,当您要将Exception包装在您自己的自定义Exception中时。 你应该这样做:
catch(Exception e) { throw new CustomException(customMessage, e); }
throw
是重新抛出一个被捕获的exception。 如果您希望在将exception传递给调用链之前对exception执行某些操作,这会非常有用。
使用不带任何参数的throw
保留调用堆栈以进行debugging。
还有一点,我没有看到任何人做出:
如果你没有在你的catch块中做任何事情,那么尝试… 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); }
如果你想要的话,你可以抛出一个新的Exception,把原来的一个设置为内部exception。
你的第二个例子将重置exception的堆栈跟踪。 第一个最准确地保留了例外的起源。 另外,你已经解开了原来的types,这是知道实际上出了什么问题的关键…如果第二个function是必需的 – 例如,要添加扩展信息或重新包装特殊types,如自定义的“HandleExceptionException”确保InnerException属性也设置了!
最重要的区别是第二个expression式会擦除exception的types。 exceptiontypes在捕捉exception中起着至关重要的作用:
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
exception, [1]
catch块会捕获exception。 但是当bar()
抛出IOException
,它将被转换为普通的Exception
ant不会被[1]
catch块捕获。
抛出或抛出ex,两者都被用来抛出或重新抛出exception,当你只是logging错误信息而不想发回任何信息给调用者时,你只需在错误中logging并离开。 但是,如果你想发送一些有关exception的有意义的信息给你使用抛出或抛出的调用者。 现在throw和throw ex之间的区别在于throw保留了堆栈跟踪和其他信息,但是throw ex会创build一个新的exception对象,因此原始堆栈跟踪将丢失。 那么我们什么时候应该使用throw和throw e,还是有一些情况需要重新抛出一个exception来重置调用堆栈信息。 例如,如果方法位于库中,并且想要从调用代码隐藏库的细节,则不一定要调用堆栈在库中包含有关私有方法的信息。 在这种情况下,您可以在库的公共方法中捕获exception,然后重新抛出exception,以便调用堆栈从这些公共方法开始。