This question was originally (and reasonably) closed as a duplicate of the following questions:
However @mklement0 and others provide a lot of details in comments in this question which deserve to be captured in a more visible and collected answer, though they may be repeated somewhat in mklement0's answers to the other questions. As I (OP) am the learner in this situation, feel free to edit the answer/provide corrections.
The core of this question (and the linked duplicates) revolves around the technical differences between $null
and "automation null" ([System.Management.Automation.Internal.AutomationNull]::Value
), a.k.a. "the enumerable null".
To answer the direct questions in the OP:
What is the difference between $a
and $c
in this situation?
$a
is $null
, while $c
is automation null. Automation null is returned via a pipeline that has no results, which can be achieved in different ways, as demonstrated by the different questions:
Get-Process | Where-Object { $_.Name -eq "oiawmij3209j23oifnoeicn" }
1,2,3,4 | ? { $_ -ge 5 }
& { }
Why does $c.PSObject.Copy()
work when $a.PSObject.Copy()
doesn't?
$c
, as automation null is technically a [PSObject]
with a PSObject
property, while $a
is just $null
.$c.PSObject
can be accessed is arguably a bug, see further context below.Why does $c.PSObject.Copy()
work when $c.GetType()
doesn't?
$c
.$c
is effectively being evaluated to $null
, and is thus equivalent to $null.GetType()
.What causes this? Is it something to do with Where-Object, or to do with PSObject.Copy(), or something else?
Where-Object
returns no results.How can I/should I reliably differentiate between/test for these cases?
[PSObject]
, and so detecting it, and differentiating it from $null
can be achieved with ($null -eq $value) -and ($value -is [PSObject])
.($null -eq $value) -and (@($value).length -eq 0)
, or ($null -eq $value) -and (@($value).count -eq 0)
.
0
, while that of @($null)
will be 1
(for reasons someone more experienced would have to explain).Further context:
$null
in expressions, but acts differently in enumeration contexts such as the pipeline, where it acts like an empty collection and therefore enumerates nothing.(& {}).psobject
and (& {}) -is [psobject]
is arguably a bug; a leaky implementation of an abstraction which reveals the fact that it is technically an object (of type [psobject]
a.k.a. [System.Management.Automation.PSObject]
, namely the aforementioned [System.Management.Automation.Internal.AutomationNull]::Value
singleton).$value -is [System.Management.Automation.Null]
.