6

Given the following script:

function f {
    [CmdletBinding()]Param()
    Write-Verbose 'f: Start'
    $t = New-Object 'System.Collections.ArrayList'
    Write-Verbose $t.GetType().Name
    return $t
}

$things = New-Object 'System.Collections.ArrayList'
$things.GetType().Name
$things = f -verbose
$things.GetType().Name

Why wouldn't the $things be-of-type ArrayList at the final line?

Adam
  • 3,891
  • 3
  • 19
  • 42

1 Answers1

10

Outputting collections (not just arrays) causes PowerShell to enumerate them by default - i.e., the collection's elements are sent one by one to the success output stream.

  • If you collect these elements by capturing the output in a variable, you always get a regular PowerShell array ([object[]]), except if there's only one element, which is captured as-is.

To prevent that - i.e., to output a collection as a whole - use:

Write-Output -NoEnumerate $t

A shorter and more efficient, but less obvious alternative is to wrap the collection in an auxiliary single-element array with the unary form of ,, the array-construction operator, which causes PowerShell to enumerate the outer array and output the collection within as-is:

, $t    # implicit output, no Write-Output needed

Note:

  • While outputting collections as a whole is more efficient, it is generally best avoided, as it may confound callers that expect PowerShell's usual, streaming enumeration behavior (one-by-one object output).
mklement0
  • 382,024
  • 64
  • 607
  • 775