在一次微软员工的代码检查中,我们在一个try{}块中发现了一大块代码。她和一位IT代表表示,这可能会对代码的性能产生影响。事实上,他们建议大部分代码应该在try/catch块之外,并且只检查重要的部分。这位微软员工补充说,即将发布的白皮书对错误的尝试/捕获块提出了警告。

我环顾四周,发现它会影响优化,但它似乎只适用于在作用域之间共享变量时。

我不是在问代码的可维护性,甚至不是在问如何处理正确的异常(毫无疑问,有问题的代码需要重构)。我也不是指使用异常进行流控制,这在大多数情况下显然是错误的。这些都是重要的问题(有些更重要),但不是这里的重点。

当不抛出异常时,try/catch块如何影响性能?


当前回答

请参阅try/catch实现的讨论,了解try/catch块如何工作,以及一些实现的开销如何高,而一些实现的开销为零。 当没有异常发生时。特别是,我认为Windows 32位实现有很高的开销,而64位实现没有。

其他回答

不。如果try/finally块排除的琐碎优化实际上对您的程序有可衡量的影响,那么您可能一开始就不应该使用. net。

我在一个紧密循环中测试了try. catch的实际影响,它本身太小,在任何正常情况下都不会成为性能问题。

如果循环只做了很少的工作(在我的测试中,我做了一个x++),您可以测量异常处理的影响。带有异常处理的循环的运行时间大约长了10倍。

如果循环做一些实际的工作(在我的测试中,我调用Int32。解析方法),异常处理的影响太小,无法测量。通过交换循环的顺序,我得到了更大的差异……

虽然“预防胜于处理”,但从性能和效率的角度来看,我们可以选择试接而不是预变。考虑下面的代码:

Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
for (int i = 1; i < int.MaxValue; i++)
{
    if (i != 0)
    {
        int k = 10 / i;
    }
}
stopwatch.Stop();
Console.WriteLine($"With Checking: {stopwatch.ElapsedMilliseconds}");
stopwatch.Reset();
stopwatch.Start();
for (int i = 1; i < int.MaxValue; i++)
{
    try
    {
        int k = 10 / i;
    }
    catch (Exception)
    {

    }
}
stopwatch.Stop();
Console.WriteLine($"With Exception: {stopwatch.ElapsedMilliseconds}");

结果如下:

With Checking:  20367
With Exception: 13998

try catch块对性能的影响可以忽略不计,但异常抛出可能相当大,这可能是你的同事感到困惑的地方。

我试了一个深接球。

        static void TryCatch(int level, int max)
        {
            try
            {
                if (level < max) TryCatch(level + 1, max);
            }
            catch
            { }
        }
        static void NoTryCatch(int level, int max)
        {
            if (level < max) NoTryCatch(level + 1, max);
        }
        static void Main(string[] args)
        {
            var s = new Stopwatch();
            const int max = 10000;
            s.Start();
            TryCatch(0, max);
            s.Stop();
            Console.WriteLine("try-catch " + s.Elapsed);
            s.Restart();
            NoTryCatch(0, max);
            s.Stop();
            Console.WriteLine("no try-catch " + s.Elapsed);
        }

结果:

try-catch 00:00:00.0008528
no try-catch 00:00:00.0002422