Ang*_*ore 9 c# if-statement switch-statement
我试图将if语句转换为切换案例(为了便于阅读)
1)我读过开关语句一般都很糟糕 - 这是真的吗? /sf/ask/426825941/
2)声明如下:
switch (Show)
{
case Display.Expense:
if (expected.EXPENSE != true)
break;
case Display.NonExpense:
if (expected.EXPENSE == true)
break;
case Display.All:
//Code
break;
}
Run Code Online (Sandbox Code Playgroud)
错误是:
控制不能从一个案例标签('案例1:')落到另一个案例标签
这是原始的if语句:
if ((Show == Display.All) || (expected.EXPENSE == true && Show == Display.Expense) || (expected.EXPENSE == false && Show == Display.NonExpense))
{
//Code
}
Run Code Online (Sandbox Code Playgroud)
Eri*_*ert 14
首先,我注意到你在第二点忘了提问.所以我要问你一些问题,以解决你的第二点:
"无法通过"错误的含义是什么?
与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;
}
Run Code Online (Sandbox Code Playgroud)
现在,可达性分析器可以确定无论采用"if"的哪个分支,切换部分端点都是不可达的.
这是好风格吗?
不.您的原始代码更具可读性.
我读过开关语句一般都很糟糕 - 这是真的吗?
意见各不相同.当存在少量非常"清晰"的替代方案时,切换语句非常有用,其行为不会以复杂的方式进行交互.有些人会告诉你,交换逻辑应该由虚拟方法或访问者模式处理,但也可以被滥用.
在这种特殊情况下我应该使用开关吗?
我不会.
你会如何改进我的代码?
if ((Show == Display.All) ||
(expected.EXPENSE == true && Show == Display.Expense) ||
(expected.EXPENSE == false && Show == Display.NonExpense))
{
//Code
}
Run Code Online (Sandbox Code Playgroud)
首先,不要在C#中为所有大写字母命名.
其次,不要将布尔人与真假相提并论.他们已经是布尔人了!如果你想知道陈述X的真实性,你就不会用英语说"X是真的吗?" 你会说"X是真的吗?"
我可能会写:
if (Show == Display.All ||
Show == Display.Expense && expected.Expense ||
Show == Display.NonExpense && !expected.Expense)
{
//Code
}
Run Code Online (Sandbox Code Playgroud)
或者,更好的是,我会将测试抽象为自己的方法:
if (canDisplayExpenses())
{
//Code
}
Run Code Online (Sandbox Code Playgroud)
或者将整个事物抽象出来:
DisplayExpenses();
Run Code Online (Sandbox Code Playgroud)
编译器不会理解你的意思.
switch (Show)
{
case Display.Expense:
if (expected.EXPENSE != true)
break;
// missing break here
case Display.NonExpense:
Run Code Online (Sandbox Code Playgroud)
编译器不会连接点,并理解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
}
Run Code Online (Sandbox Code Playgroud)
这是我写它的方式:
bool doDisplayExpected =
(Show == Display.All)
|| (Show == Display.Expense && expected.EXPENSE)
|| (Show == Display.NonExpense && !expected.EXPENSE);
if (doDisplayExpected)
{
// code
}
Run Code Online (Sandbox Code Playgroud)
你不具备在一行收拾一切.
此外,我会尝试命名属性,以便它们更容易阅读,我会重命名EXPENSE属性,IsExpense以便上面的代码将如下所示:
bool doDisplayExpected =
(Show == Display.All)
|| (Show == Display.Expense && expected.IsExpense)
|| (Show == Display.NonExpense && !expected.IsExpense);
if (doDisplayExpected)
{
// code
}
Run Code Online (Sandbox Code Playgroud)
然后,理想情况下,我会将子表达式重构为方法:
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;
}
Run Code Online (Sandbox Code Playgroud)
然后你可以将表达式放回if语句中:
if (ShowAll() || ShowExpense(expected) || ShowNonExpense(expected))
{
// code
}
Run Code Online (Sandbox Code Playgroud)
这应该更容易阅读,并在以后更改.
使用if语句并将复杂条件提取到方法中,例如
if (ShowAll() || ShowExpense())
{
}
Run Code Online (Sandbox Code Playgroud)
每次编写这样的'switch'时,请记住OOP和多态性,在该代码中添加另一个案例将是一场噩梦
PS.如果您有兴趣让你的代码干净和可读性,可以阅读由Kent Beck的Smalltalk最佳实践模式和/或清洁守则由Bob大叔 我真的很喜欢他们两个,强烈推荐.