C# 我需要试一试/接球才能投球吗?
如果我只想在异常发生时抛出一个级别的异常C# 我需要试一试/接球才能投球吗?,c#,try-catch,C#,Try Catch,如果我只想在异常发生时抛出一个级别的异常 private void TryCatch() { try { foo(); } catch (Exception ex) { throw; } } private void NoTryCatch() { foo(); } 这两种方法不一样吗 如果TryCatch中发生异常,则会向上抛出一个级别;如果NoTryCatch中发生异常,则也会向上抛出一个级别 这个问题是在使用ReSha
private void TryCatch()
{
try
{
foo();
}
catch (Exception ex)
{
throw;
}
}
private void NoTryCatch()
{
foo();
}
这两种方法不一样吗
如果TryCatch中发生异常,则会向上抛出一个级别;如果NoTryCatch中发生异常,则也会向上抛出一个级别
这个问题是在使用ReSharper并注意到它建议删除try/catch块后出现的,因为它是冗余的。这两种方法基本相同。在这种情况下,ReSharper的建议是正确的。不,您不需要尝试捕捉。您希望使用第一个函数的唯一原因是,如果您想在进一步处理该函数之前进行一些日志记录或释放资源。ReSharper是正确的。除非您确实打算捕获异常并对异常执行某些操作,否则没有必要包含try..catch块。是的,try-catch块是多余的。堆栈将一直展开,直到找到一个try/catch来处理异常。如果您所做的只是重新抛出异常,则不需要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() {}
}
使用系统;
使用系统诊断;
使用System.Runtime.CompilerServices;
公开课考试
{
const int迭代次数=100000000;
静态void Main()
{
秒表开关;
sw=秒表。开始新();
对于(int i=0;i
使用/o+/debug-
结果(三次运行):
简单方法:504495489无内联:297730603019
try/catch/throw:527445435145
我想了一些东西,但我不能100%确定,所以我去检查了一下。有时候我是对的 显然,如果您重新抛出异常(这是您的代码正在做的),那么最终可能会更改堆栈跟踪。首先,如果你要写
throw-ex代码>将重置堆栈跟踪。第二,即使在编写抛出时代码>也可能存在信息丢失的情况。看看这个和一些后续行动
当然,大多数问题都与堆栈跟踪和行号有关,这很重要,但我认为这也会影响性能,不仅仅是因为内联(或缺少内联),还因为整个异常捕获和抛出开销,但是我没有发现任何具体的东西。它们真的不一样Throw本身或Throw ex
会弄乱堆栈跟踪信息,从而使调试更加困难
捕获异常的最佳原因是向堆栈跟踪添加上下文,如:
try {
Foo();
}
catch (Exception e) {
throw new BetterException("I did something slightly silly", e);
}
这也是我的猜测,尽管我没有精力进行研究。并不是说有什么可以阻止JIT注意到在这种情况下try/catch是多余的,我怀疑,剥离它…找不到任何东西来支持我的断言。我相信不是投掷就是尝试/接球。我怀疑这实际上可能是投掷对捕获。更糟糕的效果?(5274-504)/100000000=当你开始在foo()中做一些事情时没有效果@iik:当你开始在foo()中做任何特别重要的事情时,内联无论如何都会消失。然而,在某些情况下,它可能是重要的。如果不值得这么做,MS不会让JIT能够内联,是吗?@Fred:那将是try..finally
然后不是try..catch
,对吗?