来补充Mathias R. Jessen 的有用答案:
tl;dr
使用.ForEach()数组法实现简洁且高性能的解决方案:
# Return the files' .Length property values as a collection.
(Get-ChildItem -File -Recurse -Path $path).ForEach('Length')
正如马蒂亚斯的回答所指出的,类型本机属性- 例如.Length
在数组实例上 -取得优先权越过所谓的成员访问枚举你试图执行的 - 也就是说,你想要收集.Length
的属性值elements你的集合(数组;System.IO.FileInfo实例输出Get-ChildItem),并将它们作为 ([object[]]
) array.
-
GitHub 问题 #7445讨论了这种情境模糊性并建议引入一个专职操作员, say
%.
以便您可以明确要求either定期财产访问or成员访问枚举。
成员访问枚举的一个可能令人惊讶的方面是它适用于管道逻辑在那它根据情况返回一个标量,即如果集合恰好包含one element.
- E.g.,
@(Get-Date).Year.GetType().Name
返回一个System.Int32
, not Object[]
,表示整数而不是(单个元素)array返回包含一个整数。
-
GitHub 问题 #6802讨论这个。
成员访问枚举不仅方便,而且fast,因为它避免了循环/枚举在 PowerShell 代码中.
使用ForEach-Object or Select-Object cmdlets,如马蒂亚斯的回答所示,绝对是a 功能性的 but slow解决方法由于使用了在给定情况下无法使用成员访问枚举pipeline,这对于输入来说不是必需的已经完整地存入记忆中.
所以,使用.ForEach() array method- 使用重载,您只需指定目标属性name ('Length'
) - 是一个简洁且性能更好的替代方案.
- Note: Unlike with member-access enumeration, the return value from
.ForEach()
is always a collection, albeit not an array: it is of type [System.Collections.ObjectModel.Collection[psobject]]
, which, however, will behave like an array in most contexts.[1]
[1] Unlike an array, this type of collection is extensible (you can add or remove elements). Due to the element type being [psobject]
, each element is typically invisibly wrapped in this type; e.g., 42 -is [psobject]
is $false
, but @(42).ForEach({ $_ })[0] -is [psobject]
is $true
. Unfortunately, there are cases where this near-invisible wrapper results in different behavior - see GitHub issue #5579.