我正在尝试将if语句转换为切换案例(为了便于阅读)
1)我读过开关语句一般都很糟糕 - 这是真的吗? 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:')转到另一个
这是原始的if语句:
if ((Show == Display.All) || (expected.EXPENSE == true && Show == Display.Expense) || (expected.EXPENSE == false && Show == Display.NonExpense))
{
//Code
}
答案 0 :(得分:12)
首先,我注意到你在第二点忘了提问。所以我要问你一些问题,以解决你的第二点:
“无法通过”错误的含义是什么?
与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语句一般都很糟糕 - 这是真的吗?
意见各不相同。当存在少量非常“清晰”的替代方案时,切换语句非常有用,其行为不会以复杂的方式进行交互。有些人会告诉你,交换逻辑应该由虚拟方法或访问者模式处理,但也可以被滥用。
在这种特殊情况下我应该使用开关吗?
我不会。
您如何改进我的代码?
if ((Show == Display.All) ||
(expected.EXPENSE == true && Show == Display.Expense) ||
(expected.EXPENSE == false && Show == Display.NonExpense))
{
//Code
}
首先,不要在C#中为所有大写字母命名。
其次,不要将布尔人与真假相提并论。他们已经是布尔人了!如果你想知道陈述X的真实性,你就不会用英语说“X是真的吗?”你会说“X是真的吗?”
我可能会写:
if (Show == Display.All ||
Show == Display.Expense && expected.Expense ||
Show == Display.NonExpense && !expected.Expense)
{
//Code
}
或者,更好的是,我会将测试抽象为自己的方法:
if (canDisplayExpenses())
{
//Code
}
或抽象出整件事:
DisplayExpenses();
答案 1 :(得分:7)
编译器不会理解你的意思。
switch (Show)
{
case Display.Expense:
if (expected.EXPENSE != true)
break;
// missing break here
case Display.NonExpense:
编译器不会连接点并理解break;
语句中的if
语句与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
}
你没有 将所有内容打包在一行上。
另外,我会尝试命名属性以便更容易阅读,我会将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 :(得分:5)
使用if语句并将复杂条件提取到方法中,例如
if (ShowAll() || ShowExpense())
{
}
每次写这样的'switch'时,请记住OOP和多态,添加另一个 该代码的案例将是噩梦
请参阅有关转换交换机的this和similar (C++)说明
P.S 如果您有兴趣使代码清晰易读,请考虑阅读Smalltalk Best Practice Patterns by Kent Beck和/或Clean Code by Uncle Bob 我非常喜欢他们,强烈推荐。
答案 3 :(得分:3)
如果您想要可读性,只需丢弃语法垃圾:
if (Show == Display.All || expected.EXPENSE && Show == Display.Expense || !expected.EXPENSE && Show == Display.NonExpense)
{
//Code
}
答案 4 :(得分:2)
为每个部分提供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;
}
答案 5 :(得分:1)
您收到此错误的原因是您没有定义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
}
答案 6 :(得分:0)
重构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);
}
答案 7 :(得分:0)
同意Dennis的意见,你不需要这个问题的转换案例。
虽然可能性较差,但您也可以使用更短的内容:
if (Show == Display.All || (expected.EXPENSE == (Show == Display.Expense)))
{
//Code
}