在case语句中检测到无法访问的代码
我有一个代码:
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;
它让我在rest时“检测到无法访问的代码”警告。
在这里不使用break运算符是一种好习惯吗? 我不想关闭“检测到无法访问的代码”警告。
PS:我的ProcessCmdKey方法有很多种情况 。
你的代码中有三个无法访问的语句,前两个是break语句,最后一个int是最后一行“return true”也是无法访问的,我不知道C#编译器是否检测到了,但逻辑上没有办法最后返回声明也将达成。
有多种方法可以解决这个问题,
- 存储一个名为bool retVal的临时变量,保持retVal并断开你的开关盒,并在函数结束时返回retVal。
- 如果在break之前返回值,break语句就没用了。
更好的设计方式
如果在switch case中返回值,可能很难在以后由您或其他人分析您的代码,通常最好保留一个返回值temp变量并在函数结束时返回它,这样就更容易调试和理解新编码器的代码。
交换机可能很复杂,并且交换机内的更多返回可能没有更好的控制,如果要实现日志记录,调试,从案例返回可能会很复杂。 它成为难以浏览逻辑流程图的方法。
所以最好避免返回altogather,但仍然依赖于situtations,需要在这里做出明智的决定。
如果case
语句中的所有路径都以return
结尾,则不需要break
。 不要使用它,否则你会收到上述警告。
在这种情况下,良好的做法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;
删除break
语句没有错。
您在两种情况下都使用return。 因此可以轻松删除rest。
但我宁愿把它留在那里,以防你有时会改变你的代码。
除了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;
来减少它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#,所以你需要rest一下; 在每种情况下。 哪种破坏了该块的可读性。
永远不会执行Break语句,因为您从方法返回。 所以我建议删除不必要的rest时间。
苦涩的经历教会我总是包括rest陈述,除非你真的想要通过下一个陈述,然后评论它。 否则,一个函数的行为可能会有很大的不同,因为另一个开发人员在周五下午晚些时候改变了一些事情而没有看到丢失的休
如果函数 – 无论多大 – 符合相同的if … return … else ….返回结构,你可以在函数的开头定义一个返回代码变量。 然后在case语句中分配它并在结尾处返回它,无论它结果是什么值。
存在一些误解,即C# switch
中的所有case
块必须以break
结束。 实际上,它们必须以所有代码路径中的跳转语句结束; 这可以是break
, return
, goto
甚至continue
(或当然)。 如果存在没有跳转语句的代码路径,编译器将引发错误,因此绝对没有理由在示例中进行最后的break
。 编译器不允许您将代码更改为将达到最终break
的版本,这将是添加它的时刻。
您可以将代码重写为更短且更少的重复代码:
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);
这里根本不需要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); }
由于代码当前,“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; }
我知道这并没有直接回答这个问题,但是受到各种答案的启发,我只想在“交换机”的结构上添加另一种变体:
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); }
根据你的代码,从来没有达到所有break(s)和last语句,因为之前有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); }