## Why is this an issue?

Having an infinite loop or recursion will lead to a program failure or a program never finishing the execution.

    public int Sum()
    {
        var i = 0;
        var result = 0;
        while (true) // Noncompliant: the program will never stop
        {
            result += i;
            i++;
        }
        return result;
    }

This can happen in multiple scenarios.

### Loop statements

`while` and `for` loops with no `break` or `return` statements that have exit conditions which are always `false` will be indefinitely executed.

### "goto" statements

`goto` statement with nothing that stops it from being executed over and over again will prevent the program from the completion.

### Recursion

When a recursive method call chain lacks an exit condition, the call stack will reach its limit and the program will crash due to a StackOverflowException.

    int Pow(int num, int exponent)
    {
      return num * Pow(num, exponent - 1); // Noncompliant: no condition under which Pow isn't re-called
    }

In this example, `Pow` will keep calling `Pow` with `exponent - 1` forever, until the program crashes with a StackOverflowException.

Recursion provides some benefits.

- Simplified code: recursion can often lead to more concise and elegant code by breaking down complex problems into smaller, more manageable parts.
- Improved code readability: compared to iterative solutions, recursive solutions can be easier to understand and reason about.

However, it has disadvantages as well.

- Stack overflow: Recursive functions can lead to stack overflow if the recursion is too deep, potentially causing the program to crash.
- Performance overhead: Recursive function calls can lead to poor performance due to the need to push and pop stack frames, making them potentially slower than iterative solutions.
- Difficulty in debugging: Debugging recursive code can be challenging, as multiple recursive calls can make it harder to track the flow of execution and identify logical errors.
- Space complexity: Recursive algorithms may require more memory compared to iterative approaches, as each recursive call adds a new frame to the call stack.
- Lack of control: Recursion can sometimes lead to infinite loops or unexpected behavior if not properly implemented or terminated, making it crucial to have proper base cases and exit conditions.

## How to fix it

The program’s logic should incorporate a mechanism to break out of the control flow loop. Here are some examples.

### Code examples

- Use a loop condition which eventually evaluates to `false`

#### Noncompliant code example

    public int Sum()
    {
        var i = 0;
        var result = 0;
        while (true) // Noncompliant: the program will never stop
        {
            result += i;
            i++;
        }
        return result;
    }

#### Compliant solution

    public int Sum()
    {
        var i = 0;
        var result = 0;
        while (result < 1000)
        {
            result += i;
            i++;
        }
        return result;
    }

- As {rule:csharpsquid:S907} generally suggests, avoid using `goto` statements. Instead, you can use a loop statement or explicit recursion.

#### Noncompliant code example

    public int Sum()
    {
        var result = 0;
        var i = 0;
    iteration:
        // Noncompliant: program never ends
        result += i;
        i++;
        goto iteration;
        return result;
    }

#### Compliant solution

    public int Sum()
    {
        var i = 0;
        var result = 0;
        while (result < 1000)
        {
            result += i;
            i++;
        }
        return result;
    }

- For a recursion make sure there is a base case when the recursive method is not re-called.

#### Noncompliant code example

    int Pow(int num, int exponent)
    {
      return num * Pow(num, exponent - 1); // Noncompliant: no condition under which Pow isn't re-called
    }

#### Compliant solution

    int Pow(int num, int exponent)
    {
      if (exponent > 1) // recursion is now conditional and stoppable
      {
        num = num * Pow(num, exponent - 1);
      }
      return num;
    }

## Resources

### Documentation

- Microsoft Learn - The "for" statement
- Microsoft Learn - The "while" statement
- Microsoft Learn - The "goto" statement
- Wikipedia Recursion - wiki
- Microsoft Learn - StackOverflowException class
- {rule:csharpsquid:S907} - "goto" statement should not be used

### Articles & blog posts

- Edsger Dijkstra - A Case against the GO TO Statement