David Klempfner
David Klempfner

Reputation: 9870

Testing a collection for null

Why is it, when I test a collection for null and put the collection as the first parameter, it returns the collection if it's not null, and if it is null it returns null.

I realised that if I cast it to [bool], it fixes the problem. But I thought the -eq would output a Bool value without the need for a cast?

$objectArray = @('a','b','c','d')

$objectArray -ne $null
<#
a
b
c
d
#>

[bool]($objectArray -ne $null)
#True

$objectArray -eq $null
#Nothing is outputted

[bool]($objectArray -eq $null)
#False

$null -ne $objectArray
#True

$null -eq $objectArray
#False

When I test a normal string, I get the expected results as seen below:

$object = 'a'

$object -ne $null
#True

$object -eq $null
#False

$null -ne $object
#True

$null -eq $object
#False

Upvotes: 4

Views: 427

Answers (2)

mklement0
mklement0

Reputation: 437638

To complement TessellatingHeckler's helpful answer:

To force evaluation of operators that also accept collections as the LHS to evaluate in a scalar context - and therefore return a [bool] instance rather than a filtered collection - place the scalar on the LHS:

# ALWAYS returns a [bool], because the LHS (left-hand side) is a SCALAR:
$null -eq $someVariableThatMayBeAscalarOrAnArray

If you make a habit out of this whenever you mean to perform scalar comparison to get a Boolean result, you won't be surprised if the other operand happens to be a collection.
Placing the (literal) scalar on the LHS may look odd at first, but understanding the underlying issue will help with the transition.

Upvotes: 0

TessellatingHeckler
TessellatingHeckler

Reputation: 28983

It doesn't "return the collection if it's not null", it returns the items in the collection which are not null". Any which were null would be filtered out (but there weren't any, so it doesn't change). Binary operators applied to arrays act as filters.

'a','b','c' -eq 'b'       #output is 'b'

1,2,3,4,5 -lt 3           #output is 1,2

1,2,$null,4,5 -ne $null   # output is 1,2,4,5

1,2,$null,4,5 -eq $null   # output is $null

Your code:

[bool]($objectArray -ne $null)
#True
#filters the array, returns some values
#arrays with some things in them cast to true

$objectArray -eq $null
#Nothing is outputted
# nothing in the array was null, no output.

[bool]($objectArray -eq $null)
#False
# filters the array, empty arrays cast to false

When the input to an operator is a scalar value, comparison operators return a Boolean value. When the input is a collection of values, the comparison operators return any matching values. If there are no matches in a collection, comparison operators do not return anything.

The exceptions are the containment operators (-Contains, -NotContains), the In operators (-In, -NotIn), and the type operators (-Is, -IsNot), which always return a Boolean value.

Upvotes: 3

Related Questions