如何正确使用List的ForEach()语句?

问题描述 投票:0回答:3

我很困惑我在 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>
azure powershell azure-powershell
3个回答
6
投票

问题PowerShell自己的.ForEach()

收集方法
在这种情况下被List<T>类型自己的.ForEach()
方法
抢占

  • PowerShell 自己的

    .ForEach({ ... })

    :

    • $_
       定义为脚本块参数 (
      { ... }
      )
      的输入对象
    • 将脚本块内生成的任何输出传递到(到 PowerShell 的成功输出流)。
  • 相比之下,

    List<T>

    .ForEach({ ... })
    将脚本块转换为
    Action<T>
    委托
    ,它具有以下
    含义/限制

    • 委托不知道脚本块内的$_

      ,而是接收一个必须作为$args[0]访问的单个
      参数

      脚本块的
    • 输出 被忽略,因为根据定义,Action<T>

      委托没有返回值

      虽然您可以在脚本块中使用
        Write-Host
      • 生成 主机(控制台)输出,但此类
         输出不能以
        编程方式使用,因为它绕过 PowerShell 的输出流,因此既不能被捕获也不能重定向。

PetSerAl致敬,感谢他们在评论中提供了关键指示。


解决方法

    如果您传递给
  • .ForEach()

    的脚本块不需要产生任何输出
    ,所需要做的就是在脚本块中使用 $args[0] 代替
    $_
    ,尽管您仍然可以选择使用其中之一为了避免混淆,请使用下面的其他解决方法。
    
    

  • 如果需要输出

    ,最简单的解决方案是将List<T>实例转换为

    数组
    ,首先使用.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 + '!' }
      • pipeline
      • 中的
        ForEach-Object
        (速度较慢,但不需要更改脚本块),如 No Refunds No Returns' 答案所示;例如: $list | ForEach-Object { $_ + '!' }
        
        

1
投票

$nicInfo.IpConfigurations | ForEach-Object { $ipConfiguration = $_ write-Output $ipConfiguration # do more stuff with this $ipConfiguration }



1
投票

$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()})

测试结果如下:

enter image description here 我发现了类似的

问题

,@PetSerAl 在那里解释得很好。

© www.soinside.com 2019 - 2024. All rights reserved.