web-dev-qa-db-ja.com

C#7パターンマッチング

次の例外フィルターがあるとします。

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

2つの別々の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 */ }

だから私がやりたいことをする方法があるでしょう。それともありますか?

11
Mona the Monad

同じスコープでve変数を2回宣言することはできません。ただし、ValueException<int>の変数が1回だけ宣言されるように、例外フィルターを書き直すことができます。

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

直接スローされた場合、またはAggregateExceptionにラップされている場合は、例外をキャッチするのはワンライナーです。

AggregateExceptionの目的は、複数の例外を1つの例外オブジェクトに統合することであることに注意してください。いくつかの内部例外が存在する可能性があり、それらのいくつかは集約例外である可能性もあります。したがって、集約例外をフラット化し、その内部例外をすべてチェックする必要があります。


'unwrapping'部分を拡張メソッドに入れて、コードの可読性を向上させることができます。

10

Sergeyのソリューションほど良くはありませんが、別の名前を使用してそれらを合体させることもできます。

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

    // do something with exept
}

valueExceptionのInnerExceptionsまたは一般的なValueExceptionExceptionsを同じように処理する場合。

1
Patrick Artner