web-dev-qa-db-ja.com

C#に触発された言語の例外処理を備えたif / switchステートメント構文の組み合わせ

「if」条件内で例外を試行/キャッチする必要がある場合がありますが、その後に続く本文は必要ありません。 C#では、これは実際にはかなり煩雑であり、その操作に関して一目で完全に明らかではないローカルとコードを必要とします。

「if」とは異なり、「switch」ステートメントを記述する必要がある場合もありますが、C#では かなり人気のない 構文を使用する必要があります。

これらを組み合わせるためのアイデアを次に示します。

switchtry/catchのマージ

まず、 "switch"の基本的な構文をそれに近いものに変更します かなり一般的な置換 ですが、余分な中括弧はありません。

switch (condition)
    case 1 { }
    case 2 { }
    default { }

次に、条件の例外をキャッチできるようにします。内部的には、少なくとも1つのcatchが存在する場合にのみ、適切なtry/catchブロックが挿入されます。

switch (condition)
    catch FileNotFoundException e { } // use "e"
    catch ArgumentException { }
    catch { }
    case 1 { }
    case 2 { }
    default { }

ここで、「デフォルト」を1レベル上に移動し、名前を「else」に変更することにより、if/elseチェーンに似たいくつかのそのようなステートメントのチェーンを簡単にします。

switch (condition1)
    catch FileNotFoundException { }
    case 1 { }
    case 2 { }
else switch (condition2)
    case "abc" { }
    case "def" { }
else
    { }

これで、switchtry/catchとマージされました!

「if」と組み合わせる

switchifの両方にelse句が追加されたので、自由に組み合わせてみてください。

if (bool-condition1)
    { }
else if (bool-condition2)
    { }
else switch (string-expr)
    catch FileNotFoundException { }
    case "thing" { }
else
    { }

(ありがとう ach_l !)

さらなる改善

リストまたは値の範囲を切り替える 提案されています で、簡単に組み込むことができます。

switch (int-expression)
    case 1 { }
    case 2, 5 { }
    case 10..50 { }
else switch (string-expression)
    case "abc" { }
    case "def" { }
else if (boolean-condition3)
    { }
else
    { }

この場合、条件句の値を参照できると便利です。これは、C#のusingと同じ方法で、この句で単一の変数を宣言できるようにすることで簡単に組み込むことができます。

switch (var z = int-expression)
    case 2, 5 { return z == 2 ? "two" : "five"; }
    case 10..50 { return (z * 10).ToString(); }

利点

他の利点の中でも、一般的なエラー処理シナリオを簡潔に表現できるようになりましたが、 WTFy ではありません。

switch (bool-condition)
    catch FileNotFoundException e { }
    case true { }
    case false { }

これは、あなたが遭遇した実際のコーディングの問題を解決しますか?これに適用する調整はありますか?

7
Roman Starkov

個人的には、私はifをtrueパスとオプションのfalse elseパスを使用してブール引数を評価するものとして残しますが、switchは他のオブジェクトの等価性、セットのメンバーシップなどを評価できます。これは正当な理由ではないかもしれませんが、これは、他の多くの言語でのifの動作です。その定義を変更するには、新しいプログラマーを混乱させるリスクがあると思います。

しかし、私は間違いなく、このcatchブロックの構文が便利であること、およびifsとswitchをチェーン化する機能にもユースケースがあることを確認できました。

個人的には、引数の名前がブロックによって定義されるスタイルが好きな傾向があります。さらに、条件の値が評価されている場合は、オプションでケースブロックにも指定できます。

おそらく、この例は、これに基づいて私が考えていることの範囲を明らかにするかもしれません。

if(<boolean>condition1)
    catch Exception { e -> /* exception referenced by e */ } 
    { /*true*/ } 
else switch(<any>condition2) 
   catch FileNotFoundException { /* I don't care about this exception*/ }
   case 1 {  /* I don't need condition2's value */  }
   case 2, 5, 10 .. 20 { v -> /* v is condition 2 value */ } 
   case <50 { x -> /* x is condition 2's value, this would only be evaluated if other branches are not */}
else 
   { /* !condition1 and no case evaluated in condition 2 */ }
4
Charlie