C# 如果异常过滤器的过滤器抛出异常,会发生什么
我还没有在C#6工作过,但我想知道 正如标题所说,“如果异常过滤器的过滤器抛出异常,会发生什么?”。我想真正的答案是“过滤器应该以这样一种方式编写,它永远不会抛出异常。”,但让我们说它确实如此。异常是否会发生在捕获本身内部C# 如果异常过滤器的过滤器抛出异常,会发生什么,c#,c#-6.0,C#,C# 6.0,我还没有在C#6工作过,但我想知道 正如标题所说,“如果异常过滤器的过滤器抛出异常,会发生什么?”。我想真正的答案是“过滤器应该以这样一种方式编写,它永远不会抛出异常。”,但让我们说它确实如此。异常是否会发生在捕获本身内部 try { throw new Exception("Forced Exception"); } catch (Exception ex) when (MethodThatThrowsAnException()) { WriteLine("Filtered handl
try
{
throw new Exception("Forced Exception");
}
catch (Exception ex) when (MethodThatThrowsAnException())
{
WriteLine("Filtered handler 1");
}
catch (Exception ex)
{
WriteLine("Filtered handler 2");
}
或
编辑:有趣的示例 此部分已删除,因为该示例所基于的VolatireRead中存在一个bug。需要进一步调查您可以尝试一下 正如@Habib正确指出的那样,过滤器只是被跳过,就好像它从未存在过一样。从那时起,catch子句就一直起作用。上面的例子说明了这一点 但是,如果将第二个catch子句更改为无法捕获从方法中抛出的任何内容的类型,则程序将因未处理的异常而崩溃
Spicle detail(bug):如果通过反射调用包含try-catch的方法,并且当子句引发异常时调用一个
,则认为该异常未处理,而不是原始异常。更多信息。编辑:这种奇怪的现象似乎是由volatieread中的一个bug引起的。请参考poke的回答。下面的实验不可信
因此,我做了一些实验,得出了一些有趣的结果来阐明这个问题
检查使用
打印出“过滤处理程序2”
打印出:
未处理的Expection:System.Exception:MethodThrowsanException
在Program.methodThrowsanException()在Program.Main()处
另一个有趣的输出
public void Main()
{
try
{
throw new Exception("Forced Exception");
}
catch (Exception ex) when(MethodThatThrowsAnException())
{
Console.WriteLine("Filtered handler 1");
}
catch (Exception ex) when(MethodThatThrowsAnException2())
{
Console.WriteLine("Filtered handler 2");
}
}
private bool MethodThatThrowsAnException()
{
throw new Exception("MethodThatThrowsAnException");
}
private bool MethodThatThrowsAnException2()
{
throw new Exception("MethodThatThrowsAnException2");
}
未处理的Expection:System.Exception:MethodThrowsanException2
在Program.methodThrowsanException2()在Program.Main()处
因此,它似乎试图评估第一个捕获,如果抛出异常,它将继续执行下一个捕获。第一个未失败且匹配所有条件的捕获然后处理异常(顺便说一句,是try中最初抛出的类型的异常)。但是,如果属于抛出错误类型的最后一个捕获也在筛选器部分抛出异常,则将在筛选器中抛出该类型的未处理异常。
编辑:
注:
产出:
抓住
System.Exception:程序.Main()处的强制异常
如果将其与第二个输出进行比较。。。这怎么可能呢?
在第二个示例方法中,通过抛出异常,但在最后一个示例中捕获“强制异常”如果在筛选器中抛出异常,则该异常将被静默吞没,筛选器将失败。这会导致原始异常在捕获
案例中向下移动,或最终重新向上移动
因此,调用过滤器的代码无法知道过滤器方法中实际上存在异常。因此,避免抛出异常的情况非常重要,以确保过滤器不会因此而失败
您可以在上使用以下代码进行验证:
这将导致“原始异常”出现在外部try/catch块中
更新
由于我在不使用外部try/catch块时无法理解volatireAD编译器的输出,因此我自己安装了MS Build Tools 2015(截至回答时,它仍然使用if
,而不是when
),并进行了尝试。事实证明,当不使用外部try/catch时,“原始异常”仍然是导致程序崩溃的异常。因此,这不是过滤器异常。这似乎是volatile编译器的错误。异常筛选器中引发的异常将被忽略,并将导致筛选器失败
是自v1.0以来CLR的功能。在VB.Net和F#之前,它们就可以使用了就过滤方法中的吞咽/忽略异常而言,这也是一种已定义的行为,在最近的将来不太可能改变
原始异常将向下移动到其他捕获块,或者在未被任何捕获块捕获的情况下保持未处理状态
考虑以下代码示例:
try
{
throw new Exception("Forced Exception");
}
catch (Exception ex) if (MethodThatThrowsAnException())
{
WriteLine("Filtered handler 1");
}
catch (IndexOutOfRangeException ex)
{
WriteLine("Index Out of Range");
}
方法是:
static bool MethodThatThrowsAnException()
{
throw new IndexOutOfRangeException("Index Out of Range");
}
尽管该方法正在抛出IndexOutOfRangeException
,并且在调用方代码中有一个catch
块用于该特定异常,但该方法的异常永远不会到达调用方<将忽略来自筛选器方法的code>IndexOutOfRangeException
,因为原始异常抛出新异常(“强制异常”)代码>从第一行开始,没有在任何地方处理,程序将因未处理的异常“强制异常”而崩溃
在您的第一个代码段中,由于您有一个用于基本异常的catch块
,因此第一行中的原始异常会抛出新异常(“强制异常”)代码>将在此处捕获并处理。您不会注意到前面在filter方法中抛出的异常
某种程度上说明了为什么Hejlsberg直到现在还不想包括异常过滤器。@PanagiotisKanavos也许他只是不再参与了。C#6有一些可疑的功能,看起来球队不再安全了。这个版本并没有让人想起安德斯。在一个大约48分钟开始的DotNetRocks中提到了这一点——基本上是Mads说安德斯说(意译)“我必须做什么,这样我就再也不用谈论他们了?”-大约49:30。@usr此版本为即将到来的功能攻击-模式匹配等奠定了基础。这是一项巨大的工作,但只有“少数”可见功能。毫无疑问,它们的目的在功能上下文中变得清晰。我的volat理论
public void Main()
{
try
{
throw new Exception("Forced Exception");
}
catch (Exception ex) when(MethodThatThrowsAnException())
{
Console.WriteLine("Filtered handler 1");
}
catch (Exception ex) when(MethodThatThrowsAnException2())
{
Console.WriteLine("Filtered handler 2");
}
}
private bool MethodThatThrowsAnException()
{
throw new Exception("MethodThatThrowsAnException");
}
private bool MethodThatThrowsAnException2()
{
throw new Exception("MethodThatThrowsAnException2");
}
public void Main()
{
try
{
try
{
throw new Exception("Forced Exception");
}
catch (Exception ex) when (MethodThatThrowsAnException())
{
Console.WriteLine("Filtered handler 1");
}
}
catch (Exception ex)
{
Console.WriteLine("Caught");
Console.WriteLine(ex);
}
}
private bool MethodThatThrowsAnException()
{
throw new Exception("MethodThatThrowsAnException");
}
public void Main ()
{
try
{
try
{
throw new Exception("Original exception");
}
catch (Exception ex)
when (Test()) // `if (Test())` in older previews
{
Console.WriteLine("Caught the exception");
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
public static bool Test ()
{
throw new Exception("Exception in filter condition");
}
try
{
throw new Exception("Forced Exception");
}
catch (Exception ex) if (MethodThatThrowsAnException())
{
WriteLine("Filtered handler 1");
}
catch (IndexOutOfRangeException ex)
{
WriteLine("Index Out of Range");
}
static bool MethodThatThrowsAnException()
{
throw new IndexOutOfRangeException("Index Out of Range");
}