C#7模式匹配

Mon*_*nad 9 c# pattern-matching c#-7.0

假设我有以下异常过滤器

try {
    ...
} catch (Exception e) when (e is AggregateException ae && ae.InnerException is ValueException<int> ve || e is ValueException<int> ve) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

我可以简单地写了两个单独的catch块,但我希望看到一个如何使用模式匹配功能来捕获异常,要么本身或在一个包裹AggregateException.然而,在这里,编译器抱怨重新定义ve,这是可以理解的.我见过一个模式匹配变量在同一个表达式中重用的情况,如下所示:https://blogs.msdn.microsoft.com/dotnet/2016/08/24/whats-new-in-csharp-7- 0 /

if (o is int i || (o is string s && int.TryParse(s, out i)) { /* use i */ }
Run Code Online (Sandbox Code Playgroud)

所以可能有办法做我想做的事.还是有吗?

Ser*_*kiy 10

您不能ve在同一范围内两次声明变量.但是你可以重写异常过滤器,这样变量for ValueException<int>只会声明一次:

catch(Exception e) 
  when (((e as AggregateException)?.InnerException ?? e) is ValueException<int> ve)
{
   // ...
}
Run Code Online (Sandbox Code Playgroud)

如果它被直接抛出或被包裹进去,它就是你的单线来捕获异常AggregateException.

请记住,目的AggregateException是将多个异常合并到一个异常对象中.可能存在多个内部异常,其中一些也可能是聚合异常.因此,您应该压缩聚合异常并检查其所有内部异常.


您可以将"展开"部分放入扩展方法中,以提高代码的可读性.


Pat*_*ner 5

不如 Sergey 的解决方案那么好,但您也可以使用不同的名称并将它们合并:

try 
{
    ...
} catch (Exception e) 
      when (e is ValueException<int> ve1 || 
            e is AggregateException ae  
              && ae.InnerException is ValueException<int> ve2)  
{
    var exept = ve1 ?? ve2;

    // do something with exept
}
Run Code Online (Sandbox Code Playgroud)

如果您处理 ValueException 的 InnerException 或一般 ValueException 异常,则相同。