如果条件内的开关盒

时间:2013-04-01 11:29:33

标签: c# if-statement switch-statement

我正在尝试将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
}

8 个答案:

答案 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和多态,添加另一个 该代码的案例将是噩梦

请参阅有关转换交换机的thissimilar (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
}