[英]PowerShell Array list assignment and Where-Object fails when Where-Object returns one item. Works with 2+ items
Long time searcher, first time poster.长期搜索者,第一次张贴者。 :-)
:-)
When piping an array list to Where-Object and assigning it back to another array list, a conversion error is generated when the result of the Where-Object is a single item.将数组列表传递给 Where-Object 并将其分配回另一个数组列表时,如果 Where-Object 的结果是单个项目,则会生成转换错误。 But the same command succeeds when two or more items are returned.
但是当返回两个或多个项目时,相同的命令会成功。 Is this a PowerShell bug or am I missing something?
这是 PowerShell 错误还是我遗漏了什么?
Why does this fail?为什么会失败?
PS C:\> [System.Collections.ArrayList]$AL1 = @(1,2,3)
PS C:\> [System.Collections.ArrayList]$AL2 = $AL1 | Where-Object {$_ -ge 3}
Cannot convert the "3" value of type "System.Int32" to type "System.Collections.ArrayList".
At line:1 char:1
+ [System.Collections.ArrayList]$AL2 = $AL1 | Where-Object {$_ -ge 3}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : MetadataError: (:) [], ArgumentTransformationMetadataException
+ FullyQualifiedErrorId : RuntimeException
But if the result of the Where-Object is two or more items it does not fail.但如果 Where-Object 的结果是两个或更多项,它不会失败。
PS C:\> [System.Collections.ArrayList]$AL1 = @(1,2,3)
PS C:\> [System.Collections.ArrayList]$AL2 = $AL1 | Where-Object {$_ -ge 2}
PS C:\> $AL2
2
3
PS C:\>
Also the assignment succeeds if you first create the second array list via New-Object.如果您首先通过 New-Object 创建第二个数组列表,则赋值也会成功。
PS C:\> $AL3 = New-Object System.Collections.ArrayList
PS C:\> $AL3 = $AL1 | Where-Object {$_ -ge 3}
PS C:\> $AL3
3
Tested on PSVersion 5.1.19041.1682 and core 7.0.7在 PSVersion 5.1.19041.1682 和核心 7.0.7 上测试
Yes this is expected, PowerShell enumerates all output and, since one item results from the expression:是的,这是预期的,PowerShell 枚举了所有 output 并且,因为表达式产生了一个项目:
$AL1 | Where-Object { $_ -ge 3 }
Its trying to coerce an int
to the type System.Collections.ArrayList
, however only types implementing IEnumerable
can be coerced to it, hence the error:它试图将
int
强制转换为System.Collections.ArrayList
类型,但是只能将实现IEnumerable
的类型强制转换为它,因此出现错误:
PS \> [System.Collections.ArrayList] 3
InvalidArgument: Cannot convert the "3" value of type "System.Int32" to type "System.Collections.ArrayList".
InvalidArgument:无法将类型“System.Int32”的值“3”转换为类型“System.Collections.ArrayList”。
You have three easy workarounds:您有三个简单的解决方法:
System.Collections.ArrayList
, let PowerShell dynamically assign the resulting type.System.Collections.ArrayList
类型,让 PowerShell 动态分配结果类型。@( )
, so, no matter how many elements results from the expression, the type will always be an IEnumerable
:@( )
包装您的表达式,因此,无论表达式产生多少元素,类型始终为IEnumerable
:[System.Collections.ArrayList] $AL1 = @(1, 2, 3)
[System.Collections.ArrayList] $AL2 = @($AL1 | Where-Object { $_ -ge 3 })
.Where
method instead which always returns Collection`1
(an IEnumerable
):.Where
方法,它总是返回Collection`1
(一个IEnumerable
):[System.Collections.ArrayList] $AL1 = @(1, 2, 3)
[System.Collections.ArrayList] $AL2 = $AL1.Where{ $_ -ge 3 }
Other workarounds are possible either using Write-Output -NoEnumerate
or Comma operator ,
:使用
Write-Output -NoEnumerate
或Comma operator ,
也可以使用其他解决方法:
[System.Collections.ArrayList] $AL1 = @(1, 2, 3)
[System.Collections.ArrayList] $AL2 = Write-Output ($AL1 | Where-Object { $_ -ge 3 }) -NoEnumerate
[System.Collections.ArrayList] $AL2 = , ($AL1 | Where-Object { $_ -ge 3 })
As for:至于:
Also the assignment succeeds if you first create the second array list via
New-Object
.如果您首先通过
New-Object
创建第二个数组列表,则分配也会成功。
Correct, you're not constraining the variable in this case:正确,在这种情况下您没有约束变量:
$AL3 = New-Object System.Collections.ArrayList
$AL3 = $AL1 | Where-Object { $_ -ge 3 }
$AL3.GetType() # => Int32, no longer an ArrayList
For more info, see relevant documentation: about Variables .有关详细信息,请参阅相关文档: 关于变量。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.