C#异常过滤器?

14

C#支持编译过滤器吗?过滤器是如何工作的或者它们做什么呢?

就像反编译器将一个过滤器反编译为:

try
{
}
catch(Exception e) when (?)
{
}

你可以添加一个更好的定义或示例来说明你想要的过滤器 :) - user57508
http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-334.pdf,#23.3:异常处理方式 - Roman Pokrovskij
2
另请参见:https://dev59.com/fHVC5IYBdhLWcg3wykej - Anthony Pegram
请查看此页面 http://stackoverflow.com/questions/4269189/c-exception-monitor-with-filtering ;) - Edward83
4个回答

25

自 C# 6 起,您现在可以这样做。

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

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


8

直到C# 6,C#不支持像VB一样的异常过滤器。关于它们的工作原理,请参见Eric Lippert的“Finally” Does Not Mean “Immediately”

从C# 6开始,支持异常过滤器,如C# FAQ所示

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

如果在“if”后面的括号表达式评估为真,则运行catch块,否则异常会继续传递。异常过滤器优于捕获和重新抛出,因为它们不会影响堆栈。如果异常稍后导致堆栈被转储,您可以看到它最初来自哪里,而不仅仅是最后一个重新抛出的位置。使用异常过滤器进行副作用(例如日志记录)也是一种常见且被接受的“滥用”形式。它们可以检查“飞过”的异常而不拦截其过程。在这些情况下,过滤器通常是调用返回false的帮助函数,该函数执行副作用:
private static bool Log(Exception e) { /* log it */ ; return false; }
…
try { … }
catch (Exception e) when (Log(e)) {}

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


好的,filter基本上只是一种if语句,如果不符合条件就会重新抛出它吗? - Will
3
实际上有些微妙的不同,因为如果真正的过滤器决定处理异常,它甚至不会捕获它,而使用 if 的解决方法会捕获并重新抛出异常。这在与堆栈展开相关的语义方面略有不同。 - CodesInChaos
4
C# 5 不支持异常过滤器。C# 6 支持,但它还没有正式发布。 - i3arnon
对于未来的访问者 - > C#6 支持异常过滤器。 - Mafii
感谢编辑,@Mafii!我已将其整合到答案中。 - bdukes
显示剩余3条评论

4

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

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
}

2
在C#6的最终版本中,if已被替换为when - Mafii

0

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

1)C#示例:在C# 6.0之后

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之前的示例

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

由于这段代码等同于之前的代码。这意味着它们是等价的,对吗?--- "但不,它们并不等价"
注意:异常过滤器不会解开堆栈

这里了解更多信息。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接