Командлеты сами обычно используют нет тип сбора в своих выходных данных . [1] :
Они излучают отдельные объекты к конвейеру , которые могут ситуационно означать: 0
(нет), 1
или несколько объектов.
Это точно что делает Get-ADUser
: указанное c количество выходных объектов зависит от аргументов, которые были переданы ; именно поэтому Get-AdUser
help topi c упоминает только скалярный тип ADUser
в качестве выходного типа и заявляет, что он «возвращает один или несколько» из них.
Обычно конвейер PowerShell представляет собой поток объектов , конкретная длина которых (число объектов) не должна быть заранее известна с командами при последующей обработке сегментов конвейера. выходные объекты предыдущего сегмента один за другим по мере их получения (см. about_Pipelines ).
Однако это PowerShell engine , который автоматически собирает несколько выходов для вас в массиве [object[]]
[2] при необходимости , особенно если вы захватить вывод через присвоение переменной или использовать командный вызов через (...)
как часть выражения :
# Get-ChildItem C:\Windows has *multiple* outputs, so PowerShell
# collects them in an [object[]] array.
PS> $var = Get-ChildItem C:\Windows; $var.GetType().Name
Object[]
# Ditto for an expression (...)
PS> (Get-ChildItem C:\Windows).GetType().Name
Object[]
Однако, если данная команда - возможно ситуативно - выводит только один объект тогда вы получите только этот объект сам - он не , заключенный в массив:
# Get-Item C:\ (always) returns just 1 object.
PS> $var = Get-Item C:\; $var.GetType().Name
DirectoryInfo # *not* a single-element array,
# just the System.IO.DirectoryInfo instance itself
Что может быть сложным, так это то, что данная команда может ситуационно создавать один или несколько выходов, в зависимости от входов и условий выполнения, поэтому двигатель может возвращать либо один объект , либо массив.
# !! What $var receives depends on the count of subdirs. in $HOME\Projects:
PS> $var = Get-ChildItem -Directory $HOME\Documents; $var.GetType().Name
??? # If there are *2 or more* subdirs: an Object[] array of DirectoryInfo instances.
# If there is only *one* subdir.: a DirectoryInfo instance itself.
# (See below for the case when there is *no* output.)
@()
, оператор подвыражения массива , предназначен для устранения этой неоднозначности , если необходимо: Оборачивая команду в @(...)
, PowerShell гарантирует, что ее вывод всегда , собранный как [object[]]
- даже если команда выдаст только один выходной объект или даже none :
PS> $var = @(Get-ChildItem -Directory $HOME\Projects); $var.GetType().Name
Object[] # Thanks to @(), the output is now *always* an [object[]] array.
При присвоении переменных потенциально более эффективной альтернативой является использование ограничения типа [array]
, чтобы обеспечить выходной массив:
# Alternative to @(...)
PS> [array] $var = Get-ChildItem -Directory $HOME\Documents; $var.GetType().Name
Object[]
Примечание:
Это потенциально более эффективно в этом если RHS уже является массивом, он присваивается как есть, тогда как @(...)
на самом деле перечисляет выходные данные ...
и затем собирает элементы в новый ([object[]]
) массив.
[array]
сохраняет указанный c тип входного массива, просто пропуская его через (например, [array] $var = [int[]] (1..3)
хранит массив [int[]]
как есть в $var
).
Помещение [array]
«броска» в left из $var = ...
- что делает его ограничением типа для переменной - означает, что тип переменной заблокирован в и присваивает различные значения в $var
позже продолжит преобразовывать значение RHS в [array]
([object[]]
), если необходимо (если вы не назначите $null
или "пусто" (см. ниже)).
Если команда выдаст no output, вы получите «ничто» (строго говоря: [System.Management.Automation.Internal.AutomationNull]::Value
singleton), что в большинстве случаев ведет себя как $null
[3] :
# Get-Item nomatchingfiles* produces *no* output.
PS> $null -eq (Get-Item nomatchingfiles*)
True
# Conveniently, PowerShell lets you call .Count on this value, which the
# behaves like an empty collection and indicates 0.
PS> (Get-Item nomatchingfiles*).Count
0
[1] Это можно вывести целые коллекции в целом в конвейер (в коде PowerShell с Write-Output -NoEnumerate $collection
или, более кратко, , $collection
), но тогда это просто еще один объект в конвейере, который оказывается самой коллекцией. Вывод коллекций в целом - это аномалия , однако это меняет то, как команды, которые вы передаете в , видят вывод, что может быть неожиданным; ярким примером является ConvertFrom-Json
неожиданное поведение до v7.0 .
[2] a System.Array
экземпляр, элементы которого имеют тип System.Object
, что позволяет смешивать объекты разных типов в одном массиве.
[3] Есть сценарии ios, в котором «ничто» ведет себя не так, как $null
, особенно в конвейере и в операторах switch
, как подробно описано в этом комментарии к GitHub ; связанная проблема - это запрос функции, чтобы сделать «ничто» более легко отличимым от $null
, поддерживая -is [AutomationNull]
в качестве теста.