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捕捉和投掷开销,但我没有发现任何具体的事情。
他们真的不一样。 Throw
或throw 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。 否则让它们向上传播。