Q:

Yield return and "not all code paths return value"

Why the following code:
private static IEnumerable<int> TestYield(bool check)
{
    if (check)
    {
        return 1;
    }
    else
    {
        Console.WriteLine("In the else");
    }
}

produces an error with "not all code paths return value".
However, the following code does not produce the same error:
private static IEnumerable<int> TestYield(bool check)
{
    if (check)
    {
        yield return 1;
    }
    else
    {
        Console.WriteLine("In the else");
    }
}

The only difference is the yield. What yield is making different that does not cause the same error?

A:

Any method body containing a yield break or a yield return statement is an iterator block. Within an iterator block, it's acceptable for execution to reach the closing brace of the method, as that's just equivalent to having a yield break - it's the end of the sequence.
In a regular method with a non-void return type, it's an error for the closing brace of a statement to be reachable. (Additionally, return 1; isn't a valid statement in a regular method with a return type of IEnumerable<int>.)

A:

When you use just return, because of your else statement does not return any thing, it gives you the error you mention and because you return int type it also gives the error "can not convert expression type int to return type IEnumerable".
When you use yield return, under the covers the yield keyword creates a state machine to maintain state information. According to MSDN : "When a yield return statement is reached in the iterator method, expression is returned, and the current location in code is retained. Execution is restarted from that location the next time that the iterator function is called."
Now for your question "what happens in the else side" I took a look generated IL code with ILSpy. I created a class named YTest and added method which returns with yield. Here is the generated code :
internal class YTest
{
    [IteratorStateMachine(typeof(YTest.<TestYield>d__0))]
    public static IEnumerable<int> TestYield(bool check)
    {
        int num;
        while (num == 0)
        {
            if (!check)
            {
                Console.WriteLine("In the else");
                IL_52:
                yield break;
            }
            yield return 1;
        }
        if (num != 1)
        {
            yield break;
        }
        goto IL_52;
    }
}

Compiler adds yield break statement under the hood.
When working with the yield keyword, you should keep these points in
   mind (besides msdn, quotes from https://www.infoworld.com/article/3122592/application-development/my-two-cents-on-the-yield-keyword-in-c.html
):

You cannot have the yield return statement in a try-catch block    though you can have it inside a try-finally block
You cannot have the yield break statement inside a finally block
The return type of the method where yield has been used, should be    IEnumerable, IEnumerable, IEnumerator, or IEnumerator
You cannot have a ref or out parameter in your method in which yield    has been used
You cannot use the "yield return" or the "yield break" statements    inside anonymous methods
You cannot use the "yield return" or the "yield break" statements    inside "unsafe" methods, i.e., methods that are marked with the
  "unsafe" keyword to denote an unsafe context

