If文を変換してケースを切り替えようとしています(読みやすくするため)
1)私はswitchステートメントを読んだことは全体的に素晴らしいです-それは本当ですか? https://stackoverflow.com/questions/6097513/switch-statement-inside-a-switch-statement-c
2)ステートメントは次のようになります。
switch (Show)
{
case Display.Expense:
if (expected.EXPENSE != true)
break;
case Display.NonExpense:
if (expected.EXPENSE == true)
break;
case Display.All:
//Code
break;
}
エラーは:
1つのケースラベル(「ケース1:」)から別のケースラベルに制御を移すことはできません
これは元のifステートメントです:
if ((Show == Display.All) || (expected.EXPENSE == true && Show == Display.Expense) || (expected.EXPENSE == false && Show == Display.NonExpense))
{
//Code
}
コンパイラは、ここでの意味を理解しません。
switch (Show)
{
case Display.Expense:
if (expected.EXPENSE != true)
break;
// missing break here
case Display.NonExpense:
コンパイラーはドットを接続せず、if
ステートメント内のbreak;
ステートメントがswitch
ステートメントにリンクされていることを理解します。その代わりに、break;
ステートメント自体はループから脱出するためにループでのみ使用できるため、それをループにリンクしようとします。
これは、あなたのcase
ブロックにそれを完了するためのbreak
ステートメントが欠落していることを意味し、したがってコンパイラーは不平を言います。
必要なコードをswitch
ステートメントから抽出する代わりに、元のif
ステートメントを分解します。
これはあなたの物です:
if ((Show == Display.All) || (expected.EXPENSE == true && Show == Display.Expense) || (expected.EXPENSE == false && Show == Display.NonExpense))
{
//Code
}
これは私がそれを書く方法です:
bool doDisplayExpected =
(Show == Display.All)
|| (Show == Display.Expense && expected.EXPENSE)
|| (Show == Display.NonExpense && !expected.EXPENSE);
if (doDisplayExpected)
{
// code
}
すべてを1行に詰め込むためにhaveを実行する必要はありません。
また、読みやすいようにプロパティに名前を付け、EXPENSE
プロパティの名前をIsExpense
に変更して、上記のコードが次のようになるようにします。
bool doDisplayExpected =
(Show == Display.All)
|| (Show == Display.Expense && expected.IsExpense)
|| (Show == Display.NonExpense && !expected.IsExpense);
if (doDisplayExpected)
{
// code
}
次に、理想的には、部分式をメソッドにリファクタリングします。
bool doDisplayExpected =
ShowAll()
|| ShowExpense(expected)
|| ShowNonExpense(expected);
if (doDisplayExpected)
{
// code
}
public bool ShowAll()
{
return Show == Display.All;
}
public bool ShowExpense(Expected expected)
{
return Show == Display.Expense && expected.EXPENSE;
}
public bool ShowNonExpense(Expected expected)
{
return Show == Display.NonExpense && !expected.EXPENSE;
}
次に、式をifステートメントに戻すことができます。
if (ShowAll() || ShowExpense(expected) || ShowNonExpense(expected))
{
// code
}
これは読みやすく、後で変更する必要があります。
まず、2つ目のポイントで質問するのを忘れていることに気づきました。だから私はあなたのためにいくつかの質問をするつもりです。
「通過できません」エラーの意味は何ですか?
CおよびC++とは異なり、C#では、あるスイッチセクションから別のセクションへの偶発的なフォールスルーは許可されません。すべてのスイッチセクションには、「到達不能なエンドポイント」が必要です。これは、break、goto、return、throw、または(まれに)無限ループで終了する必要があります。
これにより、休憩を入れ忘れて誤って「抜け落ちる」という一般的なバグを防ぐことができます。
フォールスルーが合法であるかのようにコードを記述しました。私の推測では、あなたはCプログラマーです。
C#でフォールスルーを強制するにはどうすればよいですか?
このような:
switch (Show)
{
case Display.Expense:
if (expected.EXPENSE != true)
break;
else
goto case Display.All;
case Display.NonExpense:
if (expected.EXPENSE == true)
break;
else
goto case Display.All;
case Display.All:
//Code
break;
}
これで、到達可能性アナライザは、「if」のどの分岐が行われたとしても、スイッチセクションのエンドポイントに到達できないと判断できます。
これはいいスタイルですか?
いいえ。元のコードはもっと読みやすくなりました。
私はswitchステートメントを読んだことは全体的に素晴らしいです-それは本当ですか?
意見はさまざまです。 switchステートメントは、動作が複雑な方法で相互作用しない非常に「鮮明な」代替手段が少数ある場合に非常に役立ちます。一部の人々は、スイッチドロジックは代わりに仮想メソッドまたはビジターパターンで処理する必要があると言いますが、それも悪用される可能性があります。
この特定のケースではスイッチを使用する必要がありますか?
私はしません。
私のコードをどのように改善しますか?
if ((Show == Display.All) ||
(expected.EXPENSE == true && Show == Display.Expense) ||
(expected.EXPENSE == false && Show == Display.NonExpense))
{
//Code
}
まず、C#ではすべて大文字で名前を付けないでください。
次に、ブール値をtrueとfalseと比較しないでください。それらはすでにブール値です!ステートメントXの真実を知りたい場合、英語で「Xが真であることは本当ですか?」とは言えません。 「Xは本当ですか?」
私はおそらく書くでしょう:
if (Show == Display.All ||
Show == Display.Expense && expected.Expense ||
Show == Display.NonExpense && !expected.Expense)
{
//Code
}
または、さらに良いことに、独自のメソッドにテストを抽象化します。
if (canDisplayExpenses())
{
//Code
}
または全体を抽象化します。
DisplayExpenses();
Ifステートメントを使用して、複雑な条件をメソッドに抽出します。
if (ShowAll() || ShowExpense())
{
}
OOPと、そのような「スイッチ」を書くたびにポリモーフィズムについて覚えておいてください。そのコードに別のケースを追加すると、悪夢になります
スイッチの変換に関する this および similar(C++) の説明を参照してください
PSコードをクリーンで読みやすくすることに興味がある場合、 Kent BeckによるSmalltalkのベストプラクティスパターン または ncle Bobによるクリーンコード 両方を本当に楽しんだので、強くお勧めします。
読みやすさが必要な場合は、構文のゴミを捨ててください:
if (Show == Display.All || expected.EXPENSE && Show == Display.Expense || !expected.EXPENSE && Show == Display.NonExpense)
{
//Code
}
エラーをスローしないように、それぞれにelse
の部分を提供しますが、他の人が言うように、この場合は実際にはswitch
は必要ありません。
switch (Show)
{
case Display.Expense:
if (expected.EXPENSE != true)
// do what you want
break;
else
// do what you want
break;
case Display.NonExpense:
if (expected.EXPENSE == true)
// do what you want
break;
else
// do what you want
break;
case Display.All:
//Code
break;
}
このエラーが発生する理由は、break
ステートメントを定義していないためです。
break
を条件付きで定義しました。
switch (Show)
{
case Display.Expense:
if (expected.EXPENSE != true)
break;
// Note that the break above is in scope of you if statement, and will
// result in a compiler error
case Display.NonExpense:
...
}
すべてのcaseステートメントに独自のbreak
があることを確認するか、caseステートメントを次のようにグループ化します。
switch (Show)
{
case Display.Expense:
case Display.All:
// do stuff
// Expense and All have the same behavior
}
if
ステートメントをリファクタリングして、次のように表現できるようにします。
if (isDisplayAll() || isExpense(expected) || isNonExpense(expected))
{
// Code
}
抽出されたロジック:
private bool isDisplayAll()
{
return (Show == Display.All);
}
private bool IsExpense(Expected expected)
{
return expected.EXPENSE && (Show == Display.Expense);
}
private bool IsNonExpense(Expected expected)
{
return !expected.EXPENSE && (Show == Display.NonExpense);
}
デニスに同意します。この問題の切り替えケースは必要ありません。
おそらく読みにくくなりますが、短くすることもできます:
if (Show == Display.All || (expected.EXPENSE == (Show == Display.Expense)))
{
//Code
}