我正在使用C#中的catch(..) when (..)
来阅读过滤器表达式,但是我找不到任何关于在评估表达式时抛出异常的情况的提及。我尝试浏览了文档和规范,但是找不到它们或未提及它们。因此,我编写了一个小程序来检查从when(..)
抛出时发生的情况。我把它放在https://dotnetfiddle.net/R7oJNp
try {
Console.WriteLine("Test(): Inside Test()");
throw new Exception("thrown from Test()");
} catch (Exception) when (AlwaysThrow()) {
Console.WriteLine("Test(): caught exception in Test()");
} catch (Exception e) {
Console.WriteLine("Test(): totally skipped last catch clause, any inner exception: " + (e.InnerException?.Message ?? "nothing"));
throw;
}
我要注意的是,如果在catch(..) when (..)
中引发异常,则会跳过整个when(..)
块。它会跳到下一个匹配的catch
块,并且在检查捕获到的异常对象时,不会发现源自when(..)
的异常。
我想知道这是否是预期的行为,以及是否有关于docs / spec的参考,说明在这种情况下会发生什么。跳过整个程序块并丢弃异常似乎很奇怪,因为这会使调试变得非常困难。
**编辑:**好的,这是.NET docs的行为,但是有什么方法可以追踪这些行为?我同意不要发生异常,并且过滤器应该足够简单,但是我们会犯错误。另外,不是应该在C#规范中提到这种行为吗?
答案 0 :(得分:5)
VB.Net在C#之前就已经支持此功能,因此您可能搜索范围太窄了:
如果在执行用户过滤的表达式期间发生异常,则该异常将被丢弃,并且过滤器表达式被视为评估为false。
https://docs.microsoft.com/en-us/dotnet/standard/exceptions/using-user-filtered-exception-handlers
答案 1 :(得分:0)
尽管具有C#6功能,但异常过滤器已supported by the CLR since .NET Framework 1.1。
表达式中的异常按以下方式处理:
如果在执行用户过滤的过程中发生异常 表达式,该异常将覆盖当前异常。在这 情况下,公共语言运行库放弃了对处理程序的搜索 对于当前异常,try构造的finally块 执行,然后从当前try构造外部开始搜索 新异常的处理程序。
答案 2 :(得分:0)
该异常被吞没且过滤器不匹配(好像它返回false):
void Main()
{
UseFilterThenCatch();
UseFilterOnly();
}
public static bool BadFilter() => throw new Exception("This will be thrown by the filter");
public static void UseFilterThenCatch()
{
try
{
throw new Exception("The exception to catch.");
}
catch(Exception) when (BadFilter())
{
Console.WriteLine("Filtered");
}
catch(Exception e)
{
Console.WriteLine("Unfiltered"); // This line gets hit.
Console.WriteLine(e.Message); // This proves it's the first exception thrown.
}
}
public static void UseFilterOnly()
{
try
{
try
{
throw new Exception("The exception to catch.");
}
catch (Exception) when (BadFilter())
{
Console.WriteLine("Filtered");
}
}
catch(Exception e)
{
Console.WriteLine("Outer catch");
Console.WriteLine(e.Message); // This proves it's the first exception thrown.
}
}
虽然这是特定于语言的,而且.NET语言可以想象做其他事情,但这是过滤器在CLR中的工作方式的组成部分,因此这是最自然的对应CIL的作用。 VB.NET和Linq表达式也发生相同的事情(在解释表达式的情况下,这花了一些刻意的工作,但对于编译表达式来说,这很容易发生,因为这也是最自然的对应CIL所做的)。 / p>