Invert “if” statement to reduce nesting

2019-01-01 16:21发布

When I ran ReSharper on my code, for example:

    if (some condition)
    {
        Some code...            
    }

ReSharper gave me the above warning (Invert "if" statement to reduce nesting), and suggested the following correction:

   if (!some condition) return;
   Some code...

I would like to understand why that's better. I always thought that using "return" in the middle of a method problematic, somewhat like "goto".

标签: c# resharper
24条回答
琉璃瓶的回忆
2楼-- · 2019-01-01 17:05

Many good reasons about how the code looks like. But what about results?

Let's take a look to some C# code and its IL compiled form:


using System;

public class Test {
    public static void Main(string[] args) {
        if (args.Length == 0) return;
        if ((args.Length+2)/3 == 5) return;
        Console.WriteLine("hey!!!");
    }
}

This simple snippet can be compiled. You can open the generated .exe file with ildasm and check what is the result. I won't post all the assembler thing but I'll describe the results.

The generated IL code does the following:

  1. If the first condition is false, jumps to the code where the second is.
  2. If it's true jumps to the last instruction. (Note: the last instruction is a return).
  3. In the second condition the same happens after the result is calculated. Compare and: got to the Console.WriteLine if false or to the end if this is true.
  4. Print the message and return.

So it seems that the code will jump to the end. What if we do a normal if with nested code?

using System;

public class Test {
    public static void Main(string[] args) {
        if (args.Length != 0 && (args.Length+2)/3 != 5) 
        {
            Console.WriteLine("hey!!!");
        }
    }
}

The results are quite similar in IL instructions. The difference is that before there were to jumps per condition: if false go to next piece of code, if true go to then end. And now the IL code flows better and has 3 jumps (the compiler optimized this a bit): 1. First jump: when Length is 0 to a part where the code jumps again (Third jump) to the end. 2. Second: in the middle of the second condition to avoid one instruction. 3. Third: if the second condition is false, jump to the end.

Anyway, the program counter will always jump.

查看更多
姐姐魅力值爆表
3楼-- · 2019-01-01 17:06

It's a matter of opinion.

My normal approach would be to avoid single line ifs, and returns in the middle of a method.

You wouldn't want lines like it suggests everywhere in your method but there is something to be said for checking a bunch of assumptions at the top of your method, and only doing your actual work if they all pass.

查看更多
人气声优
4楼-- · 2019-01-01 17:08

It doesn't only affect aesthetics, but it also prevents code nesting.

It can actually function as a precondition to ensure that your data is valid as well.

查看更多
柔情千种
5楼-- · 2019-01-01 17:08

That is simply controversial. There is no "agreement among programmers" on the question of early return. It's always subjective, as far as I know.

It's possible to make a performance argument, since it's better to have conditions that are written so they are most often true; it can also be argued that it is clearer. It does, on the other hand, create nested tests.

I don't think you will get a conclusive answer to this question.

查看更多
永恒的永恒
6楼-- · 2019-01-01 17:08

In theory, inverting if could lead to better performance if it increases branch prediction hit rate. In practice, I think it is very hard to know exactly how branch prediction will behave, especially after compiling, so I would not do it in my day-to-day development, except if I am writing assembly code.

More on branch prediction here.

查看更多
深知你不懂我心
7楼-- · 2019-01-01 17:10

There are several good points made here, but multiple return points can be unreadable as well, if the method is very lengthy. That being said, if you're going to use multiple return points just make sure that your method is short, otherwise the readability bonus of multiple return points may be lost.

查看更多
登录 后发表回答