'Blank records when returning ArrayList of PSObjects from function

So I'm refactoring a Powershell script and moving a lot of stuff into functions. When I return an ArrayList of 42 PSObjects from a function (called Get-OutList) with return $out, 42 blank records are inserted into the beginning of the ArrayList, and my original records then follow.

My function looks like this:

function Get-OutList {
    param (
        [Parameter(Position=0,mandatory=$true)]
        [PSObject]$RoleCollection,
        [Parameter(Position=1,mandatory=$true)]
        [PSObject]$MemberCollection
    )

    $out = New-Object System.Collections.ArrayList
    $MemberCollection.result | ForEach-Object {
        $currentMember = $_
        $memberDetail = New-Object PSObject
        Add-Member -InputObject $memberDetail -MemberType NoteProperty -Name FirstName -Value $($currentMember.user.first_name)
        Add-Member -InputObject $memberDetail -MemberType NoteProperty -Name LastName -Value $($currentMember.user.last_name)
        Add-Member -InputObject $memberDetail -MemberType NoteProperty -Name Email -Value $($currentMember.user.email)
        Add-Member -InputObject $memberDetail -MemberType NoteProperty -Name Status -Value $($currentMember.status)
        
        $RoleCollection.result | ForEach-Object {
            Add-Member -InputObject $memberDetail -MemberType NoteProperty -Name $_.name -Value (&{If($currentMember.roles.name -contains $_.name){"Y"}Else{""}})
        }
        $out.Add($memberDetail)
    }
    return $out
}

I understand Powershell enumerates each record back to where the function was called, and I've tried a few things to no avail:

  • Behaviour is the same in PS v5.1.x and v7.3.0.
  • Returning with return @($out) makes no difference (i.e. results in a System.Object with 42 blank records followed by my 42 original records for a total of 84 records).
  • Returning with return Write-Output -NoEnumerate $out results in a System.Object with 42 blank records and my 42 original records nested in a 43rd record.
  • Typing the result of the function call as ArrayList with $results = [System.Collections.ArrayList](Get-OutList) makes no difference.

Why can't I get my object to be the same as before it's returned from a function?? Any assistance would be greatly appreciated!

Edit #1 Including an easily-reproducible example:

function Get-OutList {
    param (
        [Parameter(Position=0,mandatory=$true)]
        [PSObject]$MemberCollection
    )

    $out = New-Object 'System.Collections.ArrayList'
    $MemberCollection | ForEach-Object {
        $memberDetail = New-Object PSObject
        Add-Member -InputObject $memberDetail -MemberType NoteProperty -Name FirstName -Value "One"
        Add-Member -InputObject $memberDetail -MemberType NoteProperty -Name LastName -Value "Two"
        Add-Member -InputObject $memberDetail -MemberType NoteProperty -Name Email -Value "Three"
        Add-Member -InputObject $memberDetail -MemberType NoteProperty -Name Status -Value "Four"
        $out.Add($memberDetail)
    }
    return $out
}

$members = @("Joe Bloggs", "Some Dude", "The Dude")

$memberDetails = Get-OutList -MemberCollection $members
Write-Output $memberDetails

If you add a breakpoint before $out is passed back, you'll see there are three records, and if you keep stepping, you should see $memberDetails will have six records (the first three blank).

Edit #2 Appears there's no such problem when using Generic.List instead of ArrayList. Used $out = [System.Collections.Generic.List[PSObject]]::new() instead of $out = New-Object 'System.Collections.ArrayList' and it's working just fine.



Solution 1:[1]

Used $out = [System.Collections.Generic.List[PSObject]]::new() instead of $out = New-Object 'System.Collections.ArrayList' and it's working just fine. No extra blankies.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Nathan C