Mic*_*tum 18 .net c# exception-handling
在C#中,throw ex
几乎总是错误的,因为它会重置堆栈跟踪.
我只是想知道,这有什么现实世界吗?我能想到的唯一原因是隐藏你的封闭库的内部,但这是一个非常薄弱的原因.除此之外,我从未在现实世界中遇到过.
编辑:我的意思是throw ex
,就像抛出完全相同的异常,但是使用空堆栈跟踪,就像完全错误一样.我知道throw ex必须作为一种语言结构存在,以允许抛出一个不同的异常(throw new DifferentException("ex as innerException", ex)
),并且只是想知道是否存在一个throw ex
没有错误的情境.
Hen*_*man 12
我从未见过它是故意使用的,但那当然没有任何意义.
让我们来看看替代方案:
catch(Exception ex)
{
// do stuff (logging)
throw; // a) continue ex
throw new SomeException("blah", ex); // b) wrap
throw new SomeException("blah"); // c) replace
throw ex; // d) reset stack-trace
}
Run Code Online (Sandbox Code Playgroud)
c)和d)都放弃了堆栈跟踪,d)唯一的'优点',我可以看到,它throw ex;
保留了确切的类型和可能的额外属性(SQL错误)ex
.
那么有没有一种情况你想要保留除堆栈跟踪之外的所有异常信息?不正常,但有些猜测:
如果你停下来想一想,它throw ex
实际上使用得相当频繁——除了未命名的局部变量。(重新)设计该语言将非常困难,以便:
throw new ArgumentException();
Run Code Online (Sandbox Code Playgroud)
是有效的,但是
var ex = new ArgumentException();
throw ex;
Run Code Online (Sandbox Code Playgroud)
无效(然后扩展它以跟踪更复杂的变量分配)。Iethrow ex
是 throw 语句的“正常”形式,但在重新抛出已捕获的异常时通常是错误的。
没有正当理由重新抛出异常对象,即“抛出 ex”。
这是一个语言\编译器功能,虽然在实践中没有增加任何价值,但它所带来的负面影响是可能的。这与能够编写代码来访问空引用上的成员的情况类似 - 这当然是可能的,但没有价值,例如:
//Possible but not useful.
object ref1 = null;
ref1.ToString();
Run Code Online (Sandbox Code Playgroud)
能够重新抛出异常对象是不幸的,并且经常被新手和经验丰富的编码人员误解,直到您在生产中遇到未处理的异常并记录了截断的堆栈跟踪。
有一种微妙的感觉,它可以用来故意隐藏堆栈跟踪信息,但抛出一个新的异常将是执行此操作的正确方法。
我什至可以说,能够重新抛出异常对象(即“抛出 ex”)是一个设计缺陷 - 很容易做错事。然而,我怀疑这是编译器出于性能原因的设计权衡,因为它会产生验证“抛出 ex”不是“重新抛出”的开销。我确信有很多这样的权衡。