C#:嵌套条件语句vs continue语句

C#:嵌套条件语句vs continue语句,c#,resharper,nested-loops,continue,C#,Resharper,Nested Loops,Continue,在最近使用ReSharper时,它建议我通过反转if条件并使用continue语句来减少某些位置的嵌套 嵌套条件: foreach(....) { if(SomeCondition) { //do some things if(SomeOtherNestedCondition) { //do some further things } } } foreach(....) {

在最近使用ReSharper时,它建议我通过反转
if
条件并使用
continue
语句来减少某些位置的嵌套

嵌套条件:

foreach(....)
{
    if(SomeCondition)
    {
        //do some things

        if(SomeOtherNestedCondition)
        {
            //do some further things
        }
    }
}
foreach(....)
{
    if(!SomeCondition) continue;

    //do some things

    if(!SomeOtherNestedCondition) continue;

    //do some further things
}
继续语句:

foreach(....)
{
    if(SomeCondition)
    {
        //do some things

        if(SomeOtherNestedCondition)
        {
            //do some further things
        }
    }
}
foreach(....)
{
    if(!SomeCondition) continue;

    //do some things

    if(!SomeOtherNestedCondition) continue;

    //do some further things
}
我理解为什么要减少性能和内存问题的嵌套,以及这两个代码片段如何相互等同的一些逻辑,但是从我的开发背景来看,前面的示例在阅读代码时更容易理解


你喜欢哪种方法?为什么?您是否在日常代码中对嵌套的ifs使用了
continue

应该没有显著的性能差异,这都是关于可读性的。我个人认为后者更容易阅读。嵌套更少,更容易阅读。

简单答案。哪一个更容易阅读和理解。

使用
继续
样式代码;您将如何处理不依赖于其他嵌套条件的第三个操作,这使得代码的顺序很重要,而IMO使其不易维护

例如:

foreach(....) 
{ 
    if(!SomeCondition) continue; 

    //do some things 

    if(!SomeOtherNestedCondition) continue; 

    //do some further things 

    if(!SomeSecondNonNestedCondition) continue;

    // do more stuff
}
当其他嵌套条件导致
继续时会发生什么将发生,但仍应执行SomeSecondNonNestedCondition


我会重构出每一位“代码”,并使用嵌套的
if()
s来调用每个重构方法,我会保留嵌套的结构。

作为一项规则,我发现最好总是在语句块开始时使用除out之外的任何条件,因为这样可以降低复杂性,但更重要的是,在进一步提高代码和内存性能之前,会抛出不兼容的环境。这也确保了您的条件在维护期间的安全性,这样就不太可能将无效场景传递到它们不属于的代码中

另外,我个人认为第二个更具可读性,因为你不会让范围层混淆可用的内容,很容易在一个层中创建一个变量,而没有意识到它在另一个层中不可用,或者必须对它们进行适当的修改,等等

这不仅仅是循环中的continue,还涉及方法应该返回的条件;而不是有一个方法开始

if (valid)
{
    do stuff;
}
它应该永远开始

if (notValid)
{
    return;
}
然而,从我的开发背景来看,阅读代码时,前面的示例更容易理解

嗯,我想,这是你个人的看法。例如,我试图避免这种嵌套,因为在我看来,它使代码更难阅读

如果你更喜欢“之前”版本而不是“之后”版本,那么就使用它
只需配置ReSharper,使其建议您真正想要的内容

请始终记住:ReSharper是一个相当“愚蠢”的重构工具——它无法取代开发人员。它只能通过做一些愚蠢的复制粘贴工作来帮助他
ReSharper所做的一些重构甚至会导致出现ReSharper所建议的相反重构的情况

因此,不要将ReSharper的建议视为最佳实践,而是视为您可以做到的可能性


顺便说一句:在这里,您应该考虑性能因素-如果性能上确实存在显著差异,我会感到惊讶。

在内存或性能方面没有差异。底层IL只是一组分支/跳转指令的选择,因此它们是跳回循环顶部还是跳回“else”语句并不重要


你应该选择哪个更容易阅读。我个人倾向于避免“continue”,但如果您有许多嵌套级别,那么您的第二个示例就更容易理解。

使用
continue
s使大部分代码处于常规过程代码级别。
否则,如果有五个检查,您将根据缩进大小将方法的“肉”缩进10或20个字符,而这些是10/20个字符,您必须滚动才能看到较长的行。

使用这两种方法的组合。如果(条件)继续,我使用
如果(条件)返回位于循环的顶部,用于验证当前状态,并将
if
语句嵌套在下面,以控制我试图完成的任何操作的流程。

简短回答: 我倾向于使用缩进,这样它意味着一些真正的决策逻辑发生了,即,预期有多个可能的执行路径的逻辑

详细回答: 与前面的“中断”语句相比,
continue
break
return
throw
),我通常更喜欢缩进的块

原因:在我看来,破坏语句通常会使代码更难阅读。如果您缩进代码,很容易找到一些决策逻辑发生的位置:这将是代码上缩进较少的第一行。如果使用带反转条件的中断语句,则必须做更多的工作来理解代码如何分支以及在何种情况下跳过某些代码

对我来说,有一个显著的例外,即在方法的开头验证参数。我将此代码的格式设置如下:

if (thisArgument == null) throw new NullArgumentException("thisArgument");
if (thatArgument < 0) throw new ArgumentOutOfRangeException("thatArgument");
...
if(thisArgument==null)抛出新的NullArgumentException(“thisArgument”);
如果(thatArgument<0)抛出新ArgumentOutOfRangeException(“thatArgument”);
...

原因:因为我不希望实际抛出这些异常(也就是说,我希望正确调用该方法;调用函数负责检测无效输入,IMO),我不想为了一些不应该发生的事情而缩进代码的其余部分。

Original
continue
意思是:当任何条件为false时,代码都不会被处理。以下是一个情况示例:

class Program
{
    static bool SomeCondition = false;
    static bool SomeOtherNestedCondition = false;
    static void Main(string[] args)
    {    
        for (int i = 0; i < 2; i++)
        {
            if (SomeCondition)
            {
                //do some things

                if (SomeOtherNestedCondition)
                {
                    //do some further things
                }
            }
            Console.WriteLine("This text appeared from the first loop.");
        }
        for (int i = 0; i < 2; i++)
        {
            if (!SomeCondition) continue;

            //do some things

            if (!SomeOtherNestedCondition) continue;

            //do some further things
            Console.WriteLine("This text appeared from the second loop.");
        }
        Console.ReadLine(); 
    }
}
类程序
{
静态bool SomeCondition=false;
静态布尔其他嵌套条件