【问题标题】:C# exception filter?C#异常过滤器?
【发布时间】:2011-05-15 04:05:45
【问题描述】:

C# 是否支持编译过滤器?过滤器是如何工作的?它们有什么作用?

像反射器一样将过滤器反编译为

尝试
{
}
catch(Exception e) when (?)
{
}

【问题讨论】:

标签: c# .net


【解决方案1】:

在 C# 6 之前,C# 不支持像 VB 那样的异常过滤器。关于它们的工作原理,请参阅 Eric Lippert 的 "Finally" Does Not Mean "Immediately"

从 C# 6 开始,支持异常过滤器,如 the C# FAQ demonstrates:

try { … } 
catch (MyException e) when (myfilter(e)) 
{ 
    … 
}

如果'if' [now when] 之后的括号表达式的计算结果为 true,则运行 catch 块,否则异常继续。

异常过滤器比捕获和重新抛出更可取,因为它们不会损坏堆栈。如果后来异常导致堆栈被转储,您可以看到它最初来自哪里,而不仅仅是它被重新抛出的最后一个地方。

使用异常过滤器产生副作用也是一种常见且公认的“滥用”形式;例如记录。他们可以检查“飞过”的异常,而不会拦截其路线。在这些情况下,过滤器通常会调用一个返回错误的辅助函数来执行副作用:

private static bool Log(Exception e) { /* log it */ ; return false; }
…
try { … }
catch (Exception e) when (Log(e)) {}

感谢 Mafii 提供 C# 6 文档的链接。

【讨论】:

  • 好的,所以 filter 基本上只是一个 if 语句,如果不满足它会重新抛出它?
  • 不,它有细微的不同,因为如果真正的过滤器决定处理异常,它甚至不会捕获它,而使用 if 的解决方法会捕获并重新抛出它。这与堆栈展开相关的语义略有不同。
  • 运行时也不同。过滤器在 catch 块之前运行,即使这些过滤器在调用堆栈中定义得更深。
  • 这个答案不再是最新的。 C# 5 确实 支持异常过滤器。看我的回答。
  • C# 5 支持异常过滤器。 C# 6 可以,但尚未正式发布。
【解决方案2】:

从 C# 6 开始,您现在可以执行此操作。

try { … }
catch (MyException e) when (myfilter(e))
{
    …
}

这与在catch 块中使用if 语句不同,使用异常过滤器不会展开堆栈。

【讨论】:

    【解决方案3】:

    C# 中的异常过滤器支持在 C# 6(Visual Studio “Dev14”)中引入:

    try
    {
        throw new ApplicationException("1");
    }
    catch (ApplicationException ex) when (ex.Message == "2")
    {
        // this one won't execute.
    }
    catch (ApplicationException ex) when (ex.Message == "1")
    {
        // this one will execute
    }
    

    【讨论】:

    • if 在 C#6 的最终版中已替换为 when
    【解决方案4】:

    在捕获异常时,如果您想以不同的方式处理异常,则可以使用异常过滤器
    -- 在 C# 6.0 之后
    -- 在 VB 7.1 之后使用 WHEN

    1) C# 6.0之后的C#样例

    try
    {
        throw new CustomException { Severity = 100 };
    }
    catch (CustomException ex) when (ex.Severity > 50)
    {
        Console.WriteLine("*BING BING* WARNING *BING BING*");
    }
    catch (CustomException ex)
    {
        Console.WriteLine("Whooops!");
    }
    

    注意:请记住顺序很重要

    2) C# 6.0 之前的 C# 示例

    try
    {
        throw new CustomException { Severity = 100 };
    }
    catch (CustomException ex)
    {
       if (ex.Severity > 50)
        {
           Console.WriteLine("*BING BING* WARNING *BING BING*");
        }
       else
        {
           Console.WriteLine("Whooops!");
        }
    }
    

    因为这段代码和上一段是等价的。意思是,它们是等价的,对吧? --- "但不,它们不等价"
    注意:异常过滤器不会展开堆栈

    阅读更多来自Here

    【讨论】:

      猜你喜欢
      • 2013-09-04
      • 1970-01-01
      • 2012-11-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-14
      • 2011-04-03
      相关资源
      最近更新 更多