8

I'm sure there is a valid reason why this happens but I don't know what it is. I have the following code

$Deleted = $Items[0].ParentNode.RemoveChild($Items[0])
Write-Output $Deleted

If I call this code using

Do-Something -OutVariable Test

I get the output on the screen and in the variable as expected, but the variable is an ArraryList with a single element that is of type XmlElement

If Instead I run

$Test = Do-Something

I don't get the output on the screen, as expected, and the returned output is a single object of type XmlElement

Why does OutVariable return an ArrayList rather than return the single item the function returns?

Thanks

1 Answer 1

11

As of PowerShell (Core) 7.3.2:

  • PowerShell unexpectedly does not unwrap a command's single-object output with
    -OutVariable
    : That is, even if a command outputs only one object, that object is unexpectedly stored as an array (array list) in the target variable whose name is passed to the common parameter -OutVariable parameter (or its alias, -ov).

  • Additionally, the type of the value stored in the target variable is always [System.Collections.ArrayList], an array list, which is inconsistent with capturing multi-object output in a variable by regular assignment, which results in System.Object[], a regular array.

See GitHub issue #3154.

Here's a concise test that demonstrates the problem:

$null = Get-Date -OutVariable ov; $ov.GetType().FullName

As of the versions listed above, this outputs:

System.Collections.ArrayList

even though the output is (conceptually) only a single [datetime] ([System.DateTime]) instance.

Contrast this with a regular assignment: $v = Get-Date; $v.GetType().FullName yields System.DateTime.


The workaround is to wrap the output-variable reference in the subexpression operator ($(...)), which gives you the same output as via the regular output (success) stream:

  • a single-element collection is unwrapped (only outputs the element itself)
  • a multi-element collection is returned as a System.Object[] array.
# Note the $(...) around $ov
PS> $null = Get-Date -OutVariable ov; $($ov).GetType().FullName
System.DateTime  # 1-element System.Collections.ArrayList unwrapped

Of course, you could also use $ov[0] if you only ever expect a single output object.

A demonstration that the workaround is effective with multi-element output too:

PS> $null = Get-ChildItem / -OutVariable ov; $($ov).GetType().FullName
System.Object[] # multi-element System.Collections.ArrayList converted to array
Sign up to request clarification or add additional context in comments.

2 Comments

i think this got fixed in 5.1.14393.2969 stackoverflow.com/questions/56799474/…
@Cataster: No, it hasn't: just try $null = Get-Date -OutVariable ov; $ov.GetType().FullName, and you'll see that even single-object output is still stored in a [System.Collections.ArrayList] instance.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.