为什么异常过滤器更适合捕获和重新抛出?

时间:2015-09-17 19:16:54

标签: c# .net exception error-handling .net-4.6

基于this question(新Exception filter功能提供哪些优势?)。

声明:

  

异常过滤器比捕获和重新抛出更可取,因为   他们没有受到伤害。如果异常后来导致堆栈   要被倾倒,你可以看到它最初的来源,而不是   只是最后一个地方被重新抛出。

在做了一些测试后,我没有看到两者之间的区别,旧的和新的,我仍然看到 rethrown 的地方的例外。所以,或者信息未被确认,我不理解异常过滤器(这就是我要问的原因),或者我做错了。你能解释一下为什么这个动作过滤器有优势吗?

class specialException : Exception
{
   public DateTime sentDateTime { get; } = DateTime.Now;
   public int code { get; } = 0;
   public string emailsToAlert { get; } = "email@domain.com";
}

然后:

        try
        {
            throw new specialException(); //line 16
            throw new Exception("Weird exception");
            //int a = Int32.Parse("fail");
        }
        catch (specialException e) when(e.code == 0)
        {
            WriteLine("E.code 0");
            throw; // <-Line 23
        }
        catch (FormatException e) 
        {
                WriteLine("cond1 " + e.GetBaseException().Message+" "+e.StackTrace);
                throw;
        }
        catch (Exception e) //when (cond2)
        {
            Console.WriteLine("cond2! " + e.Message);
                throw;
        }

结果:

enter image description here

2 个答案:

答案 0 :(得分:5)

异常过滤的优点更多地与过滤器不匹配时有关,而不是在匹配时。如果删除除第一个catch块之外的所有catch块,并将第一个when(e.code != 0)块上的过滤器更改为 try { throw new specialException(); //line 16 throw new Exception("Weird exception"); //int a = Int32.Parse("fail"); } catch (specialException e) { if(e.code != 0) { WriteLine("E.code isn't 0"); return; } throw; } ,则异常的callstack将指示它被抛出第16行。

实现这一点的旧方法如下:

throw

在这种情况下,调用堆栈将指示异常是在invokeMethod语句处抛出的,而不是在第16行。

答案 1 :(得分:3)

我将为您提供一个很好的真实世界示例,我将其用于:死锁重试循环。

有些API很好,有一个特定的DeadlockException类的东西 - 其他的,比如SOAP代理,并不完全。当你没有一个时,异常过滤器很好,以避免需要重新抛出。

int retryCount = 0;

while(true)
{
    try
    {
        // do stuff.
        break;
    }
    catch(Exception ex) when(ex.Message == "Deadlock" && ++retryCount < 10)
    {
        // retry up to 10 times.
        continue;
    }
}

这可以避免在发生非死锁异常或者重试限制被命中时抛出包装器异常。