Azure 如何正确使用List的ForEach()语句?
我不知道我在列表的ForEach方法语法中做错了什么Azure 如何正确使用List的ForEach()语句?,azure,powershell,azure-powershell,Azure,Powershell,Azure Powershell,我不知道我在列表的ForEach方法语法中做错了什么 PS D:\ntt> $nicInfo.IpConfigurations.Count 2 PS D:\ntt> $nicInfo.IpConfigurations[0] PrivateIpAddressVersion Name Primary PrivateIpAddress PrivateIpAllocationMethod Subnet Name PublicIpAddress Name ProvisioningS
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>
您是否正在尝试对集合中的每个项目进行处理?是否要执行以下操作:
$nicInfo.IpConfigurations | ForEach-Object {
$ipConfiguration = $_
write-Output $ipConfiguration
# do more stuff with this $ipConfiguration
}
仅供参考,您可以将此代码用于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()})
测试结果如下:
$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()})
正如我发现的一样,@PetSerAl在那里解释得很好。问题在于,在这种情况下,以下因素优先考虑:
PowerShell自己的。ForEach{…}:
将$定义为脚本块参数{…}的当前输入对象
将脚本块内生成的任何输出传递到PowerShell的成功输出流。
相反,List的.ForEach{…}将脚本块转换为动作委托,这具有以下含义:
委托不知道脚本块中的$u,而是接收一个必须作为$args[0]访问的参数
忽略脚本块的输出,因为定义的动作委托没有返回值
虽然您可以在脚本块内使用Write host生成主机控制台输出,但这种输出不能以编程方式使用,因为它绕过了PowerShell的输出流,因此既不能捕获也不能重定向。
在评论中提供关键指针的技巧
解决办法:
如果传递给.ForEach的脚本块不需要生成任何输出,则只需在脚本块中使用$args[0]而不是$\即可,不过为了避免混淆,您仍然可以选择使用下面的其他解决方法之一
如果需要输出,最简单的解决方案是首先将列表实例转换为一个带有.ToArray的数组,其中.ForEach按预期工作;一个简化的例子:
$list = [System.Collections.Generic.List[object]] ('foo', 'bar')
$list.ToArray().ForEach({ $_ + '!' }) # Note the .ToArray() call.
上面的结果是‘foo!’酒吧’,正如所料
或者,您可以使用:
一个foreach循环来处理列表项,这意味着您必须选择一个迭代变量名,并在循环体中引用该名称,而不是$\u1;例如。:
foreach$itm在$list中{$itm+'!'}
或者管道中的ForEach对象速度较慢,但不需要更改脚本块,如中所示;例如。:
$list | ForEach对象{$+'!'}
你是如何创建这个对象的?你确定这个方法存在吗?那使用一个呢?看起来像个虫子![咧嘴笑]方法的作用。当集合类型为Generic.List时,$\和$PSItem在.ForEach中似乎都不起作用。真有趣。。。使用写主机将输出发送到主机,但不发送$stuff。使用写输出根本不显示任何内容。这看起来像是处理输出流的一个小故障。您希望发生什么?ForEach是因为它的副作用而被执行的,而您似乎没有任何副作用。$nicInfo.IpConfigurations.ForEach{param$i write host$i}做什么?我想在ForEach语句中做一些数据操作,示例是just和example。@GregorySuvalian List有自己的方法。因此,与ForEach PowerShell相比,它更适合添加到集合中。使用$args[0]而不是$\解决了输入问题,但使用Write Host并不能解决输出问题,因为它直接打印到主机控制台,这意味着您将无法捕获或重定向该输出。@mklement0,感谢您指出,我没有意识到这一点。ᐩ1是一个有效的解决方法,但它有助于解释为什么需要它。这不是解释,因为PowerShell在v4+中的所有集合甚至标量上都提供了.ForEach方法。ForEach对象解决方案的唯一原因是,在这种情况下,特定集合类型有自己的.ForEach方法,该方法会抢占PowerShell的。要查看PowerShell的.ForEach的运行情况,请尝试1..3.ForEach{$\+1}或[collections.arraylist]1..3.ForEach{$\+1}或'foo'。ForEach{$\+'!'}感谢您的黑带解决方案@PetSerAl,但我担心它有点太复杂和晦涩,不实用。