6

I am trying to return List< T> from PowerShell function, but get one of:

  1. null - for empty list
  2. System.Int32 - for list with one element
  3. System.Object[] - for list with more elements

Code:

function CreateClrList
{
    $list = New-Object "System.Collections.Generic.List``1[System.Int32]"
    $list.Add(3)
    $list
}

Write-Host (CreateClrList).GetType()
alex2k8
  • 42,496
  • 57
  • 170
  • 221

4 Answers4

11

Yeah, powershell unrolls all collections. One solution is to return a collection containing the real collection, using the unary comma:

function CreateClrList
{
    $list = New-Object "System.Collections.Generic.List``1[System.Int32]"
    $list.Add(3)
    ,$list
}
1

Note that most of the time, you want Powershell to unroll enumerable types so that piped commands execute faster and with earlier user feedback, since commands down the pipe can start processing the first items and give output.

Ludovic Chabant
  • 1,513
  • 11
  • 12
0

If you need to return a list of ints, use jachymko's solution.

Otherwise, if you do not particularly care whether what you get is a list or array, but just want to iterate through result, you can wrap result in @() while enumerating, e.g.

$fooList = CreateClrList
foreach ($foo in @($fooList))
{
    ...
}

That would cause @($fooList) to be of array type - either an empty array, array with one element or array with multiple elements.

Community
  • 1
  • 1
ya23
  • 14,226
  • 9
  • 46
  • 43
  • 1
    In that case adding items to the internal list would not be used, `int` values could be output right away. I think the author wanted the list to be returned exactly. – Roman Kuzmin Oct 19 '12 at 07:16
  • Good point. You're probably right - that is what he said he wanted. However, it may not be the thing he ultimately wants - just providing alternative option. – ya23 Oct 19 '12 at 08:07
0

PowerShell 5.0 added support for classes and hence methods where the return type can be specified. To control the type returned, use a class with a static method:

class ListManager {
    static [System.Collections.Generic.List[int]] Create() {
        [System.Collections.Generic.List[int]] $list =
            [System.Collections.Generic.List[int]]::new()

        $list.Add(3)

        return $list
     }
}

[ListManager]::Create().GetType()