Question: I believe that C# stops evaluating an if statement condition as soon as it is able to tell the outcome. So for example:

```
if ( (1 < 0) && check_something_else() )
    // this will not be called

```

Since the condition `(1 < 0)` evaluates as `false`, the `&&` condition cannot be met, and `check_something_else()` will not be called.

How does C# evaluate an if statement with asynchronous functions? Does it wait for both to return? So for example:

```
if( await first_check() && await second_check() )
    // ???

```

Will this ever be short-circuited?

Answer: 
Yes, it will be short-circuited. Your code is equivalent to:

```cs
bool first = await first_check();
if (first)
{
    bool second = await second_check();
    if (second)
    {
        ...
    }
}

```

Note how it won't even *call* `second_check` until the awaitable returned by `first_check` has completed. So note that this won't execute the two checks in parallel. If you wanted to do that, you could use:

```cs
var t1 = first_check();
var t2 = second_check();

if (await t1 && await t2)
{
}

```

At that point:

* The two checks will execute in parallel (assuming they're genuinely asynchronous)
* It will wait for the first check to complete, and then only wait for the second check to complete *if* the first returns true
* If the first check returns false but the second check fails with an exception, the exception will effectively be swallowed
* If the second check returns false really quickly but the first check takes a long time, the overall operation will take a long time because it waits for the first check to complete first

If you want to execute checks in parallel, finishing as soon as *any* of them returns false, you'd probably want to write some general purpose code for that, collecting the tasks to start with and then using `Task.WhenAny` repeatedly. (You should also consider what you want to happen to any exceptions thrown by tasks that are effectively irrelevant to the end result due to another task returning false.)
Yes it does. You can check it yourself using [sharplab.io](https://sharplab.io/#v2:EYLgxg9gTgpgtADwGwBYA+ABATARgLABQGADAAQY4CsA3IRgMzlakDCpA3oad+YxgBzkkpALIAKAJQcuPWQEsAZmIwBOIQDoAYlAgBbAEowAzgFcANgBcxFqCZhSAZA/JqMSLToPHzVhQEMzI3sJGVkw8hwVSVoCWQBfQjigA===), the following:

```
public async Task M() {
    if(await Task.FromResult(true) && await Task.FromResult(false))
        Console.WriteLine();
}

```

Is effectively transformed by the compiler into something like:

```
TaskAwaiter<bool> awaiter;

... compiler-generated state machine for first task...

bool result = awaiter.GetResult();

// second operation started and awaited only if first one returned true    
if (result)
{
     awaiter = Task.FromResult(false).GetAwaiter();
...

```

Or as a simple program:

```
Task<bool> first_check() => Task.FromResult(false);
Task<bool> second_check() => throw new Exception("Will Not Happen");

if (await first_check() && await second_check()) {}

```

Second example on [sharplab.io](https://sharplab.io/#v2:EYLgxg9gTgpgtADwGwBYA+ABATARgLABQGADAAQY4CsA3IRgMzlakDCpA3oad+YxgBzkkpALIAKAJQceM0l1ncAlgDNSYjAE5SyxVADOAFwD6YABYwwAa0mkAZLfJa9FiADsAJifNXJE+QpkKDUlaAhkAX385MJ4MJAAeYAgIABsAPm1dQy8LaykAXgy4gDoAMSgIAFsAJRg9AFcUgzFlAEMU5wlQwISk1IznSA8cnwKMg1MKgHdSVxgZgFEEMBgABwNFNzEAIgB1RRSU0gA5CANSAAlW1dWYV22uwnCgA==).