0

In some C# code, I am evaluating some logic as I am moving code from PowerShell to C#, and ran across these differences.

    var a = false && false || true; // answer is true
    var a = true || false && false; // answer is true

However in PowerShell, the same logic:

$false -and $false -or $true # result is true
$true -or $false -and $false # result is false

The second line really seems wrong to me in c#. Is there an explanation for it, and then how can it be explained that PowerShell's logic is different?

msftrncs
  • 69
  • 3
  • 2
    they are not the same thing. [*grin*] the powershell code evals the 1st 2 items THEN evals that result against the 3rd item. it's a tad more clear if you make the sequence more obvious with parens >>> `($false -and $false) -or $true` << – Lee_Dailey Jul 28 '19 at 22:59
  • @Lee_Dailey, Sure, everything is more clear when you use parenthesis … but since you shouldn't have to, when you and the compiler both agree on the order of operations, I'm trying to understand this order of operations of logical short-circuits, and I am really puzzled that something like PowerShell wouldn't follow suit with the same language its written in. – msftrncs Jul 29 '19 at 00:38
  • 1
    according to this page >>> C# operators - C# reference | Microsoft Docs — https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/ <<< the `&&` has a higher priority than `||`. the PoSh operators do NOT have such priority. they are evaluated from left to right ... – Lee_Dailey Jul 29 '19 at 01:27

2 Answers2

4

This is a matter of operator precedence; In C# logical AND is higher precedence than Logical OR which means && it gets evaluated before ||, no matter where it is in an expression. (Unless parentheses are added).

In PowerShell, -and -or -xor have the same precedence so:

When operators have equal precedence, PowerShell evaluates them from left to right as they appear within the expression

As for why they are different, I don't know.

NB.this isn't about short-circuiting, that's doing part of the calculation, then realising that the result is already certain, and skipping the rest of the calculation. Short-circuiting doesn't change the result, only gets there quicker. See this related question about C# && and || operator precedence

TessellatingHeckler
  • 27,511
  • 4
  • 48
  • 87
  • Interesting, other sources indicated that the precedence for conditional operators were all equal, and I would have thought it made more sense to be equal, but I am also sure this comes from C/C++. – msftrncs Jul 29 '19 at 02:52
  • Looking over this page, https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/boolean-logical-operators, it looks like this situation has nothing to do with precedence, and entirely about short-circuiting. The `&&` is never evaluated. – msftrncs Jul 29 '19 at 04:09
  • @msftrncs Take the short-circuit mechanism out and evaluate the entire expression every time and nothing changes. Therefore it's not about short-circuiting. The reason the answer surprises you in C# is because it's evaluating `&&` on the right first, instead of working left-right. Therefore it's all about precedence of logical operators, which is different in both languages. Short-circuiting is (I think) the same in both languages so that's another reason it can't account for the difference. – TessellatingHeckler Jul 29 '19 at 11:18
0

So in the long run, the whole situation of precedence is EXTREMELY confusing.

Because && has higher precedence here, the expression can be rewritten so a human can start to understand it:

true || (anything && anything)

but at that point, the answer is immediately available, TRUE or anything is TRUE, so the code doesn't need to execute the AND part at all and so doesn't due to short circuiting.

PowerShell, on the other hand, has to treat them all the same (effectively (($true -or <any>) -and $false), and in this case has to evaluate operand 1 and operand 3, and never touches operand 2, since after operand 1 returned TRUE there was no need to check operand 2.

msftrncs
  • 69
  • 3