js2010's helpful answer shows how to solve the problem on the caller's side, using @()
, the array-subexpression operator, around your Set-DataHash
function call to ensure that the return value is an array.
If you want to solve the problem from within your function, you must ensure that the array being output (returned) is output as a whole, as a single object, which can be achieved with an auxiliary single-element wrapper array created with the unary form of ,
the array constructor ("comma") operator:
function Set-DataHash {
param(
[psobject] $InputObject
)
$customObject = [psobject] @{
Name = "Test"
Id = 78888
}
# Wrap $customObject in an array with @(...),
# then *additionally* wrap this array in an *auxiliary* single-element array,
# via `,` (array-construction operator).
# Outputting this aux. array causes *it* to be enumerated, which therefore
# outputs its only element as-is: the *original* array - see explanation below.
# Note: I've omitted `return`, which is always optional.
, @($customObject)
}
Explanation:
By default - irrespective of whether you use return
or implicit output in a function or script - outputting a collection (including arrays) causes its elements to be enumerated (aka streamed, unwrapped or unrolled); that is, the elements are output one by one to the (invisible, in this case) pipeline through which the caller receives the output.
In the case of a single-element collection, the nature of the pipeline is such that the caller receives just that single element itself - the collection wrapper is lost.
In the case of a multi-element collection, the specific original collection is lost too, and the enumerated elements are automatically collected in an [object[]]
array).
Therefore, wrapping a collection that you want to output as a whole, as a single object requires the aux. single-element wrapper array technique shown above; a less efficient alternative is to use Write-Output
with the -NoEnumerate
switch, which too prevents enumeration of a collection passed to it as an argument (not via the pipeline).
Note:
In general, in functions/scripts intended to be called directly by others, it is better not to output collections as a whole, so as not to confound the general expectation of streaming (enumerating) behavior in the pipeline; in the streaming case, it is the caller that must ensure that the collected output is an array, via @(...)
, as shown in js2010's answer; see this answer for background information.
Conversely, however, outputting collections as a whole is faster and allows you to output a specific collection type.