有没有真正的世界理由使用throw ex?

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.

那么有没有一种情况你想要保留除堆栈跟踪之外的所有异常信息?不正常,但有些猜测:

  • 在模糊库的边界.但c)在这里看起来更好.
  • 在调用站点上的一些生成代码,就像在RegEx类中一样.

  • 我只能说,如果你要杀死堆栈跟踪来保护你的库 IP,你最好给我一个非常好的异常消息。:) (2认同)

Dam*_*ver 5

如果你停下来想一想,它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 语句的“正常”形式,但在重新抛出已捕获的异常时通常是错误的。

  • 我认为OP的意思是当**重新抛出**异常时应该使用“throw ex;”。 (9认同)

Tim*_*oyd 4

没有正当理由重新抛出异常对象,即“抛出 ex”。

这是一个语言\编译器功能,虽然在实践中没有增加任何价值,但它所带来的负面影响是可能的。这与能够编写代码来访问空引用上的成员的情况类似 - 这当然是可能的,但没有价值,例如:

    //Possible but not useful.
    object ref1 = null;

    ref1.ToString();
Run Code Online (Sandbox Code Playgroud)

能够重新抛出异常对象是不幸的,并且经常被新手和经验丰富的编码人员误解,直到您在生产中遇到未处理的异常并记录了截断的堆栈跟踪。

有一种微妙的感觉,它可以用来故意隐藏堆栈跟踪信息,但抛出一个新的异常将是执行此操作的正确方法。

我什至可以说,能够重新抛出异常对象(即“抛出 ex”)是一个设计缺陷 - 很容易做错事。然而,我怀疑这是编译器出于性能原因的设计权衡,因为它会产生验证“抛出 ex”不是“重新抛出”的开销。我确信有很多这样的权衡。