Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does C# perform short circuit evaluation of if statements with await?

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?

like image 201
Aidan Avatar asked Sep 10 '20 08:09

Aidan


People also ask

What is the do in C?

The do-while statement lets you repeat a statement or compound statement until a specified expression becomes false.

What does |= mean in C?

The ' |= ' symbol is the bitwise OR assignment operator.


2 Answers

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

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:

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.)

like image 54
Jon Skeet Avatar answered Oct 04 '22 12:10

Jon Skeet


This is super simple to check.

Try this code:

async Task Main() {     if (await first_check() && await second_check())     {         Console.WriteLine("Here?");     }     Console.WriteLine("Tested"); }  Task<bool> first_check() => Task.FromResult(false); Task<bool> second_check() { Console.WriteLine("second_check"); return Task.FromResult(true); } 

It outputs "Tested" and nothing else.

like image 25
Enigmativity Avatar answered Oct 04 '22 13:10

Enigmativity