Powershell: Why is ([System.Collections.ObjectModel.Collection[psobject]]1)[0] a string?

Created on 23 Jun 2018  路  6Comments  路  Source: PowerShell/PowerShell

I've been using this conversion to pass objects to PowerShell.Invoke() like this:

PowerShell.Invoke([System.Collections.ObjectModel.Collection[psobject]]$obj)

I'm puzzled by this conversion from [int32] to [string].

Steps to reproduce

([System.Collections.ObjectModel.Collection[psobject]]1)[0].GetType().Name

Expected behavior

I expected 1 to remain an [int32].

int32

Actual behavior

1 is converted to a [string]

string

Environment data

> $PSVersionTable
Name                           Value
----                           -----
PSVersion                      6.1.0-preview.688
PSEdition                      Core
GitCommitId                    v6.1.0-preview.688
OS                             Microsoft Windows 6.3.9600
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0
Issue-Discussion WG-Engine

All 6 comments

I have no explanation, but 2 quick additional observations:

  • It only happens when you cast a _scalar_; ([System.Collections.ObjectModel.Collection[psobject]] (, 1))[0].GetType().Name yields Int32, as expected.

  • It also happens with [System.Collections.Generic.List[object]]; by contrast:

    • casting a scalar to [System.Collections.ArrayList] _fails_,
    • but works _correctly_ with [object[]]

It looks like { Write-Object $obj -NoEnumerate }.Invoke() is a more reliable way to convert to [Collection[psobject]]. Or at least is was before #2038, and (hopefully) will be again once those issues are corrected. In the meantime Write-Output2 from 6451(comment) seems to work.

If you're not concerned about the intermediate, transient [object[]] array that is invariably constructed, you can also do [System.Collections.Generic.List[object]] @($obj)

 // If the original object was a number, then try and do a conversion on the string 
 // equivalent of that number... 

Interesting. That is clearly deliberate. But why do that?

I'm not sure this really is deliberate, I think another explanation is that this is just a symptom of PowerShell being especially permissive with conversions.

Based on this check: https://github.com/PowerShell/PowerShell/blob/bbb4f2ea84f6c4a8e8775978178826b61db20bda/src/System.Management.Automation/engine/LanguagePrimitives.cs#L5395 it feels like an oversight to have allowed the conversion to collections other than array.

Was this page helpful?
0 / 5 - 0 ratings