在case语句中检测到无法访问的代码

时间:2010-04-15 08:13:09

标签: c#

我有一个代码:

    protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
    {
        switch (keyData)
        {
            case Keys.Alt|Keys.D1:

                if (this._condition1)
                {
                    return true;
                }
                else
                {
                    return base.ProcessCmdKey(ref msg, keyData);
                }

                break;

            case Keys.Control |Keys.U:

                if (this._condition2)
                {
                    return true;
                }
                else
                {
                    return base.ProcessCmdKey(ref msg, keyData);
                }

                break;

            default:

                return base.ProcessCmdKey(ref msg, keyData);
        }

        return true;

它让我在休息时发现“无法检测到的代码”警告。

这里不使用break运算符是不错的做法?我不想关闭“检测到无法访问的代码”警告。

PS:我的ProcessCmdKey方法中有很多 case

14 个答案:

答案 0 :(得分:19)

你的代码中有三个无法访问的语句,前两个是break语句,最后一个int最后一行“return true”也是无法访问的,我不知道C#编译器是否检测到了,但逻辑上没有方式也将达到最后一个退货声明。

有多种方法可以解决这个问题,

  1. 存储一个名为bool retVal的临时变量,保持retVal并断开你的开关案例,并在函数返回retVal的末尾。
  2. 如果你在休息前返回值,break语句就没用了。
  3. 更好的设计方式

    如果在switch case中返回值,可能很难在以后由您或其他人分析您的代码,通常最好保留一个返回值temp变量并在函数结束时返回它,这会变得更容易调试并理解新编码器的代码。

    交换机可能很复杂,并且交换机内的更多返回可能没有更好的控制,如果要实现日志记录,调试,从案例返回可能会很复杂。它变得难以浏览逻辑流程图。

    所以最好避免返回altogather,但仍然依赖于situtations,需要在这里做出明智的决定。

答案 1 :(得分:18)

如果break语句中的所有路径都以case结尾,则无需{p> return。不要使用它,否则你会收到上述警告。

答案 2 :(得分:9)

在这种情况下,良好的做法imho将结束每个案件的回报,如下:

case Keys.Alt|Keys.D1:
    bool result;
    if (this._condition1) 
        { 
            result = true; 
        } 
        else 
        { 
            result = base.ProcessCmdKey(ref msg, keyData); 
        }
    return result;

或者

case Keys.Alt|Keys.D1:
    bool result = (this._condition1)
        ? true
        : base.ProcessCmdKey(ref msg, keyData); 
    return result;

答案 3 :(得分:5)

此处删除break语句没有任何问题。

答案 4 :(得分:3)

在两种情况下都使用return。因此可以轻松删除休息。

但我更愿意将它留在那里,以防你有时会改变你的代码。

答案 5 :(得分:3)

除了从那里删除break;行之外,您还可以删除else语句。因为您从第一个if返回,所以不需要它。

所以你的代码可能会这样:

protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
    switch (keyData)
    {
        case Keys.Alt|Keys.D1:
            if (this._condition1)
                return true;                

            return base.ProcessCmdKey(ref msg, keyData);

        case Keys.Control |Keys.U:
            if (this._condition2)
                return true;

            return base.ProcessCmdKey(ref msg, keyData);

        default:
            return base.ProcessCmdKey(ref msg, keyData);
    }

    return true;
}

您可以删除return true;行并反转if语句,从而进一步减少它,因为无论如何返回true和方法结束:

protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
    switch (keyData)
    {
        case Keys.Alt|Keys.D1:
            if (!this._condition1)
                return base.ProcessCmdKey(ref msg, keyData);

            break;

        case Keys.Control |Keys.U:
            if (!this._condition2)
                return base.ProcessCmdKey(ref msg, keyData);

            break;

        default:
            return base.ProcessCmdKey(ref msg, keyData);
    }

    return true;
}

编辑:我忘记了你不能使用C#,所以你需要休息一下;在每种情况下。哪种方式破坏了该区块的可读性。

答案 6 :(得分:2)

永远不会执行Break语句,因为您从方法返回。所以我建议删除不必要的休息。

答案 7 :(得分:1)

苦涩的经历教会我总是包括休息陈述,除非你真的想要落实到下一个陈述,即便如此,评论它。否则,一个函数的行为可能会有很大的不同,因为另一个开发人员在周五下午晚些时候发生了变化,并没有看到丢失的休息时间。

如果函数 - 无论多大 - 符合相同的if ... return ... else ....返回结构,你可以在函数的开头定义一个返回代码变量。然后在case语句中分配它,并在结尾处返回它,无论结果是什么值。

答案 8 :(得分:1)

您可以将代码重写为更短且重复性更低的代码:

bool ret = false;
switch(keyDate){
    case Keys.Alt | Keys.D1:
         ret = this._condition1;
    break;
    case Keys.Control |Keys.U:
         ret = this._condition2;
    break;
    default: break;
 }
 return ret || base.ProcessCmdKey(ref msg, keyData);

答案 9 :(得分:1)

存在一定的误解,即C#case中的所有switch块必须以break结尾。实际上,它们必须以所有代码路径中的跳转语句结束;这可以是breakreturngoto甚至continue(当然还是throw)。如果存在没有跳转语句的代码路径,编译器将引发错误,因此示例中的最终break绝对没有理由。编译器不允许您将代码更改为将达到最终break的版本,这将是添加它的时刻。

答案 10 :(得分:0)

这里根本不需要switch语句,完全避免了这个问题:

protected override bool ProcessCmdKey(ref Message msg, Keys keyData) 
{ 
    return
        (keyData == Keys.Alt|Keys.D1 && this._condition1) ||
        (keyData == Keys.Control|Keys.U && this._condition2) ||
        base.ProcessCmdKey(ref msg, keyData); 
}

答案 11 :(得分:0)

由于代码是当前的,“break”命令永远不会运行,也不会运行最终的“return true”命令。删除这些将消除警告。

您可能希望尝试使用较少返回路径的解决方案,因为它可能使代码更难以调试和理解。像这样:

    protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
    {
        bool processed = false;
        switch (keyData)
        {
            case Keys.Alt | Keys.D1:

                if (this._condition1)
                    processed = true;

                break;

            case Keys.Control | Keys.U:

                if (this._condition2)
                    processed = true;

                break;
        }

        if (!processed)
            processed = base.ProcessCmdKey(ref msg, keyData);

        return processed;
    }

答案 12 :(得分:0)

据我所知,这并没有直接回答这个问题,但是受到各种答案的启发,我只想在“开关”的结构上添加另一种变体:

protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
    if (keyData == Keys.Alt|Keys.D1 && _condition1)
        return true;

    if (keyData == Keys.Control|Keys.U && _condition2)
        return true;

    // ...repeat for other variations

    return base.ProcessCmdKey(ref msg, keyData);
}

答案 13 :(得分:-1)

根据你的代码,从来没有达到所有的break和s语句,因为之前有return语句。

您可以像这样重写代码:

    switch (keyData)
    {
        case Keys.Alt|Keys.D1:
            if (this._condition1) return true;
            else goto default;

        case Keys.Control |Keys.U:
            if (this._condition2) return true;
            else goto default;

        default:
            return base.ProcessCmdKey(ref msg, keyData);
    }