我想知道是否有任何方法可以简化 C# 中的以下复杂分支结构? 请注意,"do C;"出现两次。 谢谢。
if (condition1)
{
if (condition2)
{
do A;
if (condition3 on result of doing A)
{
do B;
}
else
{
do C;
}
}
else
{
do C;
}
}
else
{
do D;
}
do E;
您可以简化它,以便C()
只出现一次。
您的代码等效于
if (condition1)
{
if (condition2)
{
if (A())
{
B();
}
else
{
C();
}
}
else
{
C();
}
}
else
{
D();
}
E();
其中A()
方法返回一个bool
,等效于您的condition3 on result of doing A)
。
查看此简化,请注意您可以替换:
if (condition2)
{
if (A())
{
B();
}
else
{
C();
}
}
else
{
C();
}
跟:
if (condition2 && A())
{
B();
}
else
{
C();
}
所以最终的代码看起来像这样:
if (condition1)
{
if (condition2 && A())
{
B();
}
else
{
C();
}
}
else
{
D();
}
E();
这不是一个巨大的改进,但现在它只提到了一次C()
。
您也可以将其编写为开关,但我个人认为这不是改进(我知道这是一个主观问题):
switch (condition1)
{
case true when condition2 && A():
B();
break;
case true:
C();
break;
default:
D();
break;
}
E();
注意: 当然,把condition2 && A()
而不是A() && condition2
通常,这种场景的问题是环形复杂性,代码很难阅读。尝试简化代码的一种方法是使用return
。
try
{
if (condition1)
{
if (condition2)
{
if (A())
{
B();
return;
}
}
C();
return;
}
D();
}
finally
{
E();
}
有时这给了你一个更好的代码,更易读。但事实并非如此。最终代码或多或少是相同的,并且具有许多缩进级别。我包括只是因为有时可能是一种选择。
另一种方式是分而治之。创建一个减少嵌套的方法:
if (condition1)
{
if (condition2)
{
OnBothConditions();
}
else
{
C();
}
}
else
{
D();
}
E();
并以其他方法委派:
private void OnBothConditions()
{
if (A())
{
B();
}
else
{
C();
}
}
您还可以创建此方法:
private void OnCondition1()
{
if (condition2)
{
OnBothConditions();
}
else
{
C();
}
}
并更改您的代码:
if (condition1)
{
OnCondition1();
}
else
{
D();
}
E();
还有其他选项,比如 Matthew Watson 一个,是正确的,更紧凑,但我更喜欢代码更具可读性而不是更紧凑的代码,因为您必须维护该代码,并且在 6 或 10 个月内可能很难理解这种"优化"。
我现在写下来后看到这个答案在某种程度上是马修沃森和维克多的混合,但我还是会提供它。
首先,我同意 Victor 的观点,即摆脱所有嵌套是一项重要的改进。我也同意他们的观点,即将代码拆分为方法在这方面非常有帮助。
其次,我同意Matthew的观点,如果do A
的结果可以直接用来定义condition3
的结果,也可以直接使用,而不是在评估condition3
之前调用它。
如果可以将condition3
提取到将do A
的结果作为输入参数的方法中,则可以通过为每个嵌套级别创建一个方法来完全避免嵌套。举个例子:
public static void Main()
{
DoYourThing();
do E;
}
DoYourThing()
{
if (<condition1>)
{
DoYourNextThing();
}
else
{
do D;
}
}
DoYourNextThing()
{
if (<condition2> && Condition3(A()))
{
do B;
}
else
{
do C;
}
}
private bool Condition3(object a)
{
//...
}
如果无法将condition3
提取到将do A
的结果作为输入参数的方法,则可能需要以不同的方式实现DoYourNextThing()
。一种可能性是:
DoYourNextThing()
{
if (ShouldDoB())
{
do B;
}
else
{
do C;
}
}
ShouldDoB()
{
if (!condition2)
{
return false;
}
var a = do A;
return condition3; // based on a
}
作为旁注,我想说的是,使用描述性变量名和方法名通常比重构嵌套循环更重要;而同时做这两件事(以增强理解和可读性的方式)是黄金。
话虽如此,我相信OP使用通用名称只是为了提供一个清晰易懂的逻辑示例。