Как правильно использовать оператор ForEach () List? - PullRequest
0 голосов
/ 18 декабря 2018

Я запутался, что я делаю неправильно в синтаксисе метода ForEach в List?

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>

Ответы [ 3 ]

0 голосов
/ 18 декабря 2018

Просто для справки, вы можете использовать этот код для 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()})

Результат теста, как показано ниже:

enter image description here

Как и я нашел этот аналог проблема , @PetSerAl очень хорошо объяснила там.

0 голосов
/ 19 декабря 2018

Проблема заключается в том, что Собственный метод сбора PowerShell .ForEach() является вытесненным собственным List<T> типом .ForEach()метод в этом случае:

  • Собственный PowerShell .ForEach({ ... }):

    • определяет $_ в качестве входного объекта под рукой дляАргумент блока скрипта ({ ... })
    • пропускает любые выходные данные, созданные внутри блока скрипта (в поток вывода успешных результатов PowerShell).
  • В отличие от этого,List<T> .ForEach({ ... }) преобразует блок скрипта в Action<T> делегат, что имеет следующие последствия:

    • Делегат не знает о $_ внутри скриптавместо этого он получает один аргумент , к которому необходимо обращаться как $args[0].

    • Вывод из блока скрипта игнорируется, потому что у делегата Action<T> по определению нет возвращаемого значения .

      • В то время как вы можете создать host (console) с выводом Write-Host из блока скрипта, такой вывод не может использоваться программно , поскольку он обходит выходные потоки PowerShell и поэтому не может быть ни захвачен, ни перенаправлен.

Наконечник шляпы PetSerAl для предоставления важнейших указателей в комментариях.

Временные решения :

  • Если блок скрипта, который вы передаете .ForEach() , не должен выводить , все, что нужно, это использовать $args[0] вместо $_ в вашем блоке сценариев, хотя вы все равно можете использовать один из других обходных путей ниже, чтобы избежать путаницы.

  • Если вывод необходим самое простое решение - преобразовать экземпляр List<T> в массив с .ToArray() first , для которого .ForEach() работает как положено;упрощенный пример:

    $list = [System.Collections.Generic.List[object]] ('foo', 'bar')
    $list.ToArray().ForEach({ $_ + '!' }) # Note the .ToArray() call.
    

    Выше приведено 'foo!', 'bar!', как и ожидалось.

    • В качестве альтернативы , вы можете использовать:

      • цикл foreach для обработки элементов списка, что означает, что вы должны выбрать имя переменной итерации и ссылаться на него вместо $_ в теле цикла;Например:
        foreach ($itm in $list) { $itm + '!' }
      • или ForEach-Object в конвейере (медленнее, но не требует изменения блока скрипта), как показано в Нет возврата средств НетВозвращает ответ ;Например:
        $list | ForEach-Object { $_ + '!' }
0 голосов
/ 18 декабря 2018

Вы пытаетесь что-то сделать с каждым предметом в коллекции?Вы хотите сделать что-то вроде этого:

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