1

I am trying to understand why in the following example the script-block returning a List-object returns null. Eventhough with other types it works perfectly fine.

$s1 = {
    param($string);
  $list = [System.Collections.Generic.List[object]]::new();
    return $list; 
}
$s2 = {
    param($string);
  return 'test'; 
}

$r1 = (Invoke-Command -ScriptBlock ($s1) -ArgumentList('something'));
$r2 = (Invoke-Command -ScriptBlock ($s2) -ArgumentList('something'));
write-host ($null -eq $r1); # True
write-host ($null -eq $r2); # False
write-host ($r1); # <empty>
write-host ($r2); # test

The result from the above snippet is:

True
False

test

I would expect:

False
False
System.Collections.Generic.List`1[System.Object]
test

Can somebody help me understand why the $s1 scriptblock would return $null?

2
  • Classic PowerShell gotha, use the unary comma: return ,$list; Commented Oct 18, 2021 at 9:08
  • FYI: PowerShell Gotchas Commented Oct 18, 2021 at 14:08

1 Answer 1

2

PowerShell loves to enumerate (or unroll) collections, including [List]'s, which is exactly what happens here.

To suppress this behavior, use Write-Output -NoEnumerate:

$s1 = {
    param($string)
    $list = [System.Collections.Generic.List[object]]::new()
    return Write-Output $list -NoEnumerate
}
Sign up to request clarification or add additional context in comments.

3 Comments

That seems to do the trick, thanks powershell for this weirdness :P. But just to understand it better. 'unroll' means converting it to a pipe-line (e.i. I could use Foreach-Object on it)?
@n247s Well, the inverse - the auto-unrolling happens primarily so that ForEach-Object (and other cmdlets) can consume pipeline input 1-by-1
The idea behind the PowerShell Pipeline is to unravel any collections and pass (stream) each individual item to a number of consecutive cmdlets similar to workstations in a manufacturing line.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.