В случае ForEach-Object
или любого командлета, предназначенного для работы с коллекцией, использование -InputObject
в качестве прямого параметра не имеет смысла, поскольку командлет предназначен для работы с коллекцией, которая должна бытьразвернул и обработал по одному элементу за раз. Однако я бы также не назвал параметр «бесполезным», потому что он все еще должен быть определен, чтобы его можно было разрешить для ввода через конвейер.
Почему это так?
-InputObject
- это условное имя общего параметра для того, что следует считать входным конвейером. Это параметр с [Parameter(ValueFromPipeline = $true)]
, установленным на него, и как таковой он лучше подходит для получения входных данных из конвейера. скорее принят в качестве прямого аргумента. Основным недостатком передачи его в качестве прямого аргумента является то, что коллекция не гарантированно будет развернута и может демонстрировать некоторые другие действия, которые могут быть не предназначены. На странице about_pipelines
, указанной выше:
Когда вы передаете несколько объектов в команду, PowerShell отправляет объекты команде по одному . Когда вы используете параметр команды, объекты отправляются как один объект массива. Это незначительное различие имеет значительные последствия.
Чтобы объяснить приведенную выше цитату другими словами, передача коллекции (например, массива или списка) через конвейер автоматически развернет коллекцию и передаст ееследующая команда в конвейере по одному. Командлет сам не развертывает -InputObject
, данные доставляются по одному элементу за раз. Вот почему вы можете столкнуться с проблемами при прямой передаче коллекции параметру -InputObject
- поскольку командлет, вероятно, не предназначен для развертывания самой коллекции , он ожидает, что каждый элемент коллекции будет передан ему в видепоштучно.
Рассмотрим следующий пример:
# Array of hashes with a common key
$myHash = @{name = 'Alex'}, @{name='Bob'}, @{name = 'Sarah'}
# This works as intended
$myHash | Where-Object { $_.name -match 'alex' }
Приведенный выше код выводит следующее, как и ожидалось:
Name Value
---- -----
name Alex
Но если вы передаете хеш как InputArgument
прямо так:
Where-Object -InputObject $myHash { $_.name -match 'alex' }
Возвращает всю коллекцию, потому что -InputObject
никогда не развертывался так, как при передаче через конвейер, но в этом контексте $_.name -match 'alex'
по-прежнему возвращает true. Другими словами, при предоставлении коллекции в качестве прямого параметра для -InputObject
, она обрабатывается как отдельный объект, а не выполняется каждый раз для каждого элемента в коллекции . Это также может дать видимость работы должным образом при проверке на ложное условие для этого набора данных:
Where-Object -InputObject $myHash { $_.name -match 'frodo' }
, который в итоге ничего не возвращает, потому что даже в этом контексте frodo
не является значением какого-либо из ключей name
в коллекции хэшей.
Короче говоря, если что-то ожидает, что ввод будет передан в качестве ввода конвейера, обычно, если не всегда, более безопасная ставкасделать это таким образом, особенно при передаче в коллекцию. Однако если вы работаете с не-коллекцией, то, скорее всего, не возникнет проблем, если вы решите использовать параметр -InputObject
напрямую.