如果条件内的开关盒

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)


ang*_*son 7

编译器不会理解你的意思.

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)

这应该更容易阅读,并在以后更改.


ill*_*ant 5

使用if语句并将复杂条件提取到方法中,例如

if (ShowAll() || ShowExpense())
{
}
Run Code Online (Sandbox Code Playgroud)

每次编写这样的'switch'时,请记住OOP和多态性,在该代码中添加另一个案例将是一场噩梦

有关转换开关的详细信息,请参见此类(C++)指令

PS.如果您有兴趣让你的代码干净和可读性,可以阅读由Kent Beck的Smalltalk最佳实践模式和/或清洁守则由Bob大叔 我真的很喜欢他们两个,强烈推荐.