ТЛ; др
В условных / неявных логических контекстах PowerShell:
Одиночные -элементные массивы обрабатываются как скаляры : то есть их один-единственный элемент сам интерпретируется как логическое значение. [1]
2 + -элементы массива всегда $true
независимо от их содержания.
С массивом в качестве LHS , операторы с поддержкой массива, такие как -eq
, неизменно также , вывод , массив .
Поскольку все элементы массива $null
и вы сравниваете с $null
, ваше сравнение будет эффективным no-op - например, @( $null ) -eq $null
приведет к @( $null )
- и ваши условия эквивалентно:
[bool] @( $null, $null ) # -> $true - array with 2+ elements is always $True
[bool] @( $null ) # -> $false(!) - treated like: [bool] $null
Возможно, что удивительно, неявная логическая логика применяет конвейерную логику к массиву :
То есть массив с одним -элементом (концептуально) развернут , а его элемент интерпретируется как логическое значение.
Следовательно, [bool] @( $null )
обрабатывается так же, как [bool] $null
, то есть $false
.
Обычно @( <one-and-only-element> )
(или , <one-and-only-element>
) обрабатывается так же, как <one-and-only-element>
в логическом контексте.
Напротив, , если массив имеет 2 или более элементов , это всегда $true
в логическом контексте , даже если все его элементы будут индивидуально считаться $false
.
Обходной путь для проверки, является ли произвольный массив пустым :
В качестве условия укажите .Count
свойство:
if ( (<array>).Count ) { $true } else { $false }
Вы можете добавить -gt 0
, но это не является строго необходимым, потому что любое ненулевое значение неявно $true
.
Применительно к вашему примеру:
PS> if ( ( @($null) -eq $null ).Count ) { $true } else { $false }
True
Проверка произвольного значения для (скалярного) $null
:
if ($null -eq <value>) { $true } else { $false }
Обратите внимание, как $null
необходимо использовать в качестве LHS , чтобы не дать логике фильтрации массива вступить в силу, если <value>
будет массивом.
Это также причина, по которой код Visual Studio с расширением PowerShell рекомендует «$ null должен быть слева от сравнений», если вы пишете что-то вроде $var -eq $null
.
[1] Сводка по булевому преобразованию :
Среди скаляров :
Ниже приведены неявно $false
:
Подводный камень : Любая непустая строка оценивается как $true
например, [bool] 'False'
is $true
Обратите внимание, что это отличается от явного разбора строки : [bool]::Parse('false')
возвращает $false
(и $true
для 'true'
, но больше ничего не распознает).
Экземпляры любого другого (не относящегося к коллекции) типа неявно $true
, включая типы [pscustomobject]
и [hashtable]
(которые PowerShell обрабатывает как отдельный объект, а не как коллекция записей).
Среди коллекций , таких как массивы (точнее, типы, подобные коллекциям, которые реализуют интерфейс IList
- см. исходный код ):
Пусто Коллекции всегда $false
, так же как и специальное значение "нулевой коллекции", указывающее на отсутствие вывода команды [System.Management.Automation.Internal.AutomationNull]::Value
.
Подводные камни : Одноэлементные коллекции оценивать по:
- Если единственным элементом является скаляр : его логическое значение
- Если этот элемент сам по себе является collection :
$true
, если он содержит хотя бы 1 элемент (независимо от того, что это за элемент).
2 + -элементные коллекции всегда $true
.