我对List的ForEach方法语法中做错的事情感到困惑吗?
PS D:\ntt> $nicInfo.IpConfigurations.Count
2
PS D:\ntt> $nicInfo.IpConfigurations[0]
PrivateIpAddressVersion Name Primary PrivateIpAddress PrivateIpAllocationMethod Subnet Name PublicIpAddress Name ProvisioningState
----------------------- ---- ------- ---------------- ------------------------- ----------- -------------------- -----------------
IPv4 ipconfig1 True 10.233.0.4 Dynamic Succeeded
PS D:\ntt> $nicInfo.IpConfigurations.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True List`1 System.Object
PS D:\ntt> $nicInfo.IpConfigurations.ForEach({$_})
PS D:\ntt>
答案 0 :(得分:2)
问题是在这种情况下, PowerShell's own .ForEach()
collection method被the List<T>
type's own .ForEach()
method 抢占了
PowerShell自己的.ForEach({ ... })
:
$_
定义为脚本块参数({ ... }
)的输入对象相反,List<T>
的{{1}}将脚本块转换为.ForEach({ ... })
委托,具有以下含义:
委托人不了解脚本块内的Action<T>
,而是收到一个必须以$_
访问的单个参数。
输出被忽略 ,因为根据定义,$args[0]
委托没有返回值。
Action<T>
生成 host (控制台)输出,但不能帽子PetSerAl的提示,用于在评论中提供关键的指针。
解决方法:
如果您传递给Write-Host
的脚本块不需要产生任何输出,那么只需使用.ForEach()
代替$args[0]
在您的脚本块中,尽管您仍然可以选择使用以下其他解决方法之一,以避免造成混淆。
如果需要输出 ,最简单的解决方案是使用$_
将List<T>
实例转换为 array 首先,.ToArray()
将按预期工作;一个简化的例子:
.ForEach()
上面的代码按预期产生$list = [System.Collections.Generic.List[object]] ('foo', 'bar')
$list.ToArray().ForEach({ $_ + '!' }) # Note the .ToArray() call.
。
或者,您可以使用:
'foo!', 'bar!'
循环来处理列表项,这意味着您必须选择一个迭代变量名称并在循环体中引用该变量而不是foreach
;例如:$_
foreach ($itm in $list) { $itm + '!' }
在管道中(速度较慢,但不需要更改脚本块),如No Refunds No Returns' answer所示;例如:ForEach-Object
答案 1 :(得分:1)
您是否要对集合中的每个项目进行处理?您想做这样的事情吗?
$nicInfo.IpConfigurations | ForEach-Object {
$ipConfiguration = $_
write-Output $ipConfiguration
# do more stuff with this $ipConfiguration
}
答案 2 :(得分:1)
仅供参考,您可以将此代码用于list.ForEach()。
$nicInfo.IpConfigurations.ForEach({write-host $args[0].ToString()})
我自己测试一下,它可以工作。示例代码如下:
$s=New-Object System.Collections.Generic.List[string]
$s.Add("hello_1")
$s.Add("hello_2")
$s.Add("hello_3")
$s.ForEach({write-host $args[0].ToString()})
测试结果如下:
和我发现类似的issue一样,@ PetSerAl在这里的解释也很好。