Командлеты сами обычно используют no тип коллекции в своих выводах. [1]:
Они выдают < em> отдельные объекты в конвейер, что может ситуативно означать: 0
(нет), 1
или несколько.
Это именно то, что делает Get-ADUser
: конкретное количество объектов вывода зависит от заданных аргументов; поэтому в Get-AdUser
разделе справки упоминается только скалярная введите ADUser
в качестве типа вывода и состояния что он возвращает один или несколько из них.
Как правило, конвейер PowerShell представляет собой поток объектов, конкретная длина которого (количество объектов) не требуется заранее знать, а команды в последующих сегментах конвейера обрабатывают предыдущие объекты вывода сегмента один за другим по мере их получения (см. about_Pipelines).
Однако это движок PowerShell, который автоматически собирает для вас несколько выходных данных в [object[]]
массив [2] при необходимости. , особенно если вы захватываете вывод с помощью назначения переменной или используете вызов команды через (...)
, оператор группировки (или $(...)
, оператор подвыражения [3] < / sup>) как выражение:
# 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 with (...) (and also with $(...) and always with @(...))
PS> (Get-ChildItem C:\Windows).GetType().Name
Object[]
Однако, если данная команда - возможно, ситуативно - выводит только единственный объект, тогда вы получите только этот объект сам < / strong> - он не заключен в массив:
# 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 гарантирует, что ее вывод всегда em > собраны как [object[]]
- даже если команда создает только один объект вывода или даже ни одного:
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 уже является массивом, он назначается как есть, тогда как @(...)
фактически перечисляет вывод из ...
, а затем повторно собирает элементы в массив new ([object[]]
).
[array]
preserves the specific type of an input array by simply passing it through (e.g., [array] $var = [int[]] (1..3)
stores the [int[]]
array as-is in $var
).
Размещение преобразования [array]
слева от $var = ...
- что делает его ограничением типа для переменной - означает, что тип переменной заблокирован в , а присвоение других значений $var
позже продолжит преобразование значения RHS в [array]
([object[]]
), если это необходимо (если вы не назначите $null
или ничего (см. ниже)).
Если команда выводит no, вы ничего не получите (строго говоря: _ 31_ singleton), который в большинстве случаев ведет себя как $null
[4] < / sup>:
# 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
s неожиданное поведение до версии 7.0.
[2] экземпляр System.Array
, элементы которого типа System.Object
, что позволяет смешивать объекты разных типов в одном массиве.
[3] Обычно достаточно использовать (...)
; $(...)
требуется только для интерполяции строк (расширяемые строки) и для встраивания целых операторов или нескольких команд в большее выражение; обратите внимание, что $(...)
, в отличие от (...)
, разворачивает одноэлементные массивы; сравните (, 1).GetType().Name
с $(, 1).GetType().Name
; см. этот ответ.
[4] Существуют сценарии, в которых ничто не отличается от $null
, особенно в конвейере и в операторах switch
, как подробно описано в этот комментарий на GitHub; связанная проблема - это запрос функции, чтобы ничто не было легче отличить от $null
, путем поддержки -is [AutomationNull]
в качестве теста.
person
mklement0
schedule
01.02.2020