C#我是否需要TRY / CATCH才能投掷?

如果我想要做的就是在exception发生时将其抛出一个级别?

private void TryCatch() { try { foo(); } catch (Exception ex) { throw; } } private void NoTryCatch() { foo(); } 

这两种方法不一样吗?

如果在TryCatch中发生exception,它将被抛出一个级别,如果在NoTryCatch中发生exception,exception也将被抛出一个级别。

在使用ReSharper之后出现了这个问题并注意到它建议删除try / catch块,因为它是多余的。

是的,那些方法几乎(*)相同。 唯一的区别是在第一个断点很容易。 我总是选择第二个,除非我真的需要在那里打破并且只在那里(而不是立即抛出任何类型的例外,这很容易)。 即使我曾经使用过第一个,我也会在提交代码之前将它放回第二个表单。

(*)JIT处理它们的方式可能存在一些差异。 第一个将结束更多的IL,这将影响内联的机会等。

编辑:我无法抗拒一点微基准测试。 看起来try / catch / throw对性能的影响比禁用内联更糟糕:

 using System; using System.Diagnostics; using System.Runtime.CompilerServices; public class Test { const int Iterations = 1000000000; static void Main() { Stopwatch sw; sw = Stopwatch.StartNew(); for (int i=0; i < Iterations; i++) { SimpleMethod(); } sw.Stop(); Console.WriteLine("Simple method: {0}", sw.ElapsedMilliseconds); sw = Stopwatch.StartNew(); for (int i=0; i < Iterations; i++) { NoInlining(); } sw.Stop(); Console.WriteLine("No inlining: {0}", sw.ElapsedMilliseconds); sw = Stopwatch.StartNew(); for (int i=0; i < Iterations; i++) { TryCatchThrow(); } sw.Stop(); Console.WriteLine("try/catch/throw: {0}", sw.ElapsedMilliseconds); } static void SimpleMethod() { Foo(); } [MethodImpl(MethodImplOptions.NoInlining)] static void NoInlining() { } static void TryCatchThrow() { try { Foo(); } catch (Exception) { throw; } } static void Foo() {} } 

/o+ /debug-编译

结果(三次运行):

简单方法:504,495,489
无内联:2977,3060,3019
try / catch / throw:5274,4543,5145

不,你不需要尝试捕获。 您想要使用第一个函数的唯一原因是,如果您想在进一步处理函数之前执行一些日志记录或释放资源。

这两种方法基本相同。 在这种情况下,ReSharper的建议是正确的。

我想到的东西,但我不确定100%,所以我去检查。 我有时候是对的。

显然,如果您重新抛出exception(这是您的代码正在执行的操作),您最终可能会更改堆栈跟踪。 首先,如果你要写throw ex; 这将重置堆栈跟踪。 第二,即使写作throw; 也可能存在缺少信息的情况。 请参阅此文章以及一些用户评论 。

当然,大多数这些问题都与堆栈跟踪和行号有关,这些问题很重要,但我认为这也会影响性能,不仅仅是因为内联(或缺乏内联),还因为整体exception捕捉和投掷开销,但我没有发现任何具体的事情。

他们真的不一样。 Throwthrow ex堆栈跟踪信息,可以使调试更加困难。

捕获exception的最佳理由是向堆栈跟踪添加上下文,例如:

 try { Foo(); } catch (Exception e) { throw new BetterException("I did something slightly silly", e); } 

ReSharper是正确的。 除非你真的打算捕获并对exception做一些事情,否则包括try..catch块在内没有任何意义。

是的,try catch块是多余的。 堆栈将被解开,直到找到try / catch来处理exception。

如果您只是重新抛出exception,则不需要try / catch块。 通常,只有在可以处理exception时才应该捕获exception。 否则让它们向上传播。