Weird ceilling to access the array

I came across a strange piece of code in PowerShell when using an array indexer. Why do you think that he behaves as follows?

The standard behavior that I would expect is to get the exact member of the array each time, in this case first with a zero value

(0, 1)[0] == 0 # as expected (0, 1 -ne 2)[0] == 0 # as expected regardless second member would be casted from bool to int (0, 1 -ne 0)[0] == 1 # magic starts here 

Until now, I would expect something with the result of cast 1 -ne 0 from bool to int, and together with 0 in the first place of the array, it forms something as a known exception, but:

 (0, 60 -ne 0)[0] == 60 # ignores first member and whole (-ne 0) part (0, 60 -ne 1)[0] == 0 # as expected (1, 60 -ne 0)[0] == 1 # as expected 

At this moment, it seems that it takes effect only if the first member is 0 , regardless of whether it is passed as a variable, and the second part must be exactly 1 -ne 0

 # doesn't matter if first member is variable $x = 0 ($x, 1 -ne 0)[0] == 1 # same magic as before ($x, 0 -ne 1)[0] == 0 # as expected by may be caused by leading zero of 0 -ne 1 ($x, 0 -ne 0)[0] == null # this is also very weird ($x, 1 -ne 1)[0] == 0 # maybe return of bool comparison or simply first member, I would expect null as before 

I understand that anyone interested in these things will be resolved by simply preventing the bool and int code from mixing in arrays. As I found it to be used in our legacy code used as ceilling

 return ([int]$lastResultCode, 1 -ne 0) 

instead:

 if ($lastResultCode == 0) return 1 else return $lastResultCode 

But consider the scenario when this code is already in the air and cannot change this code, but also on this computer there may be updates to the PowerShell version and therefore may change behavior in the future. For such a scenario, I would like to please you for your opinion on what causes this behavior.

+5
source share
1 answer

There are two things here:

  • An operator has a higher priority than comparison operators. So, expressions like:

     (0, 1 -ne 0)[0] 

    actually analyzed as:

     ((0, 1) -ne 0)[0] 

    You can learn more about PowerShell statement priority in the about_Operator_Precedence section.

  • PowerShell comparison operators can work with scalars (single elements) as well as arrays. When you use them with an array, they will return all elements matching the conditions:

     PS > (4, 5, 3, 1, 2) -gt 2 # All items greater than 2 4 5 3 PS > (4, 5, 3, 1, 2) -ne 3 # All items that do not equal 3 4 5 1 2 PS > 

With these considerations in mind, the behavior you see can be easily explained. Expression:

 (0, 1 -ne 0)[0] 

first analyzed as:

 ((0, 1) -ne 0)[0] 

which then becomes:

 (1)[0] 

because -ne returns elements from (0, 1) that are not equal to 0 , which is just 1 .


The solution is to simply use an extra set of parentheses:

 (0, (1 -ne 0))[0] 

This will force PowerShell to first evaluate part 1 -ne 0 and behave as you would expect:

 PS > (0, (1 -ne 0)) 0 True PS > (0, (1 -ne 0))[0] 0 PS > 
+6
source

All Articles