Why does select-object -first 1 not return an array for consistency?

Viewed 1247

When I pipe some objects to select-object -first n it returns an array except if n is 1:

PS C:\> (get-process | select-object -first 1).GetType().FullName
System.Diagnostics.Process

PS C:\> (get-process | select-object -first 2).GetType().FullName
System.Object[]

For consistency reasons, I'd have expected both pipelines to return an array.

Apparently, PowerShell chooses to return one object as object rather than as an element in an array.

Why is that?

2 Answers

Why questions are generally indeterminate in cases like this, but it mostly boils down to:

  1. Since we asked for the "-first 1" we would expect a single item.
  2. If we received an array/list we would still need to index the first one to obtain just that one, which is pretty much what "Select-Object -First 1" is designed to do (in that case.)
  3. The result can always be wrapped in @() to force an array -- perhaps in the case where we've calculated "-First $N" and don't actually know (at that moment in the code) that we might receive only 1.
  4. The designer/developer thought it should be that way.

It's #3 that keeps it from being an issue:

$PSProcess = @(Get-Process PowerShell | Select -First 1)

...this will guarantee $PSProcces is an array no matter what the count.

It even works with:

$n = Get-Random 3
@(Get-Process -first $n) # $n => 0, 1, or 2 but always returns an array.

The pipeline will return the [System.Diagnostics.Process] object. In your first example it's only one object. The second one is an [System.Object[]] array of the [System.Diagnostics.Process].

$a = (get-process | select-object -first 1)
$a | Get-Member

$b = (get-process | select-object -first 2)
,$b | Get-Member
Related