ТЛ; др
Чтобы сравнить значение с $null
с -eq
или -ne
, всегда сделайте $null
LHS :
$null -eq $psCustomObject.x # NOT $psCustomObject.x -eq $null
Порядок операндов имеет значение, потому что операторы сравнения в PowerShell действуют как фильтры с значениями массива значения LHS.
Кроме того, даже при сравнении с чем-то отличным от $null
порядок операндов может иметь значение из-за неявных преобразований типов.
Операторы сравнения PowerShell , такие как -eq
, по конструкции работают по-разному с значениями массива LHS и, следовательно, какой операнд находится там, где имеет значение даже для обычно коммутативных операторов
-eq
и -ne
.
С a скаляр LHS (одно значение), оператор сравнения возвращает Boolean ($True
или $False
, который указывает на результат сравнения.
- Однако даже при размещении операндов скаляров может иметь значение , как отмечает Джефф Цейтлин , а именно с операндами различных типов : обычно RHS операнд приводится к типу данных LHS перед сравнением ; Например,
' 2 ' -eq 2
выполняет сравнение строк (приводит целое число 2
к строке '2'
) и, следовательно, возвращает $False
, тогда как 2 -eq ' 2 '
выполняет сравнение integer (преобразует строку ' 2 '
к [int]
) и поэтому возвращает $True
.
С массивом -значным LHS (значения LHS, являющимся коллекцией), оператор сравнения возвращает массив ([object[]]
), поскольку он действует как фильтр : оператор применяется к элементам входного массива индивидуально , и возвращается подмассив тех элементов, для которых возвращена операция $True
.
Обратите внимание, что в Windows PowerShell v5.1 / PowerShell Core 6.1.0 PowerShell поддерживает операнды со значениями массива только как операнд LHS ; Операнды RHS должны быть скалярами или приводиться к одному. [1]
Следовательно, в вашем примере $null -eq $psCustomObject.x
и $psCustomObject.x -eq $null
являются не взаимозаменяемыми и тестируют различные условия :
# Is the RHS $null?
# Whether the concrete RHS value is then a scalar or an array doesn't matter.
$null -eq $psCustomObject.x
# * If $psCustomObject.x is a scalar: is that scalar $null?
# * If $psCustomObject.x is an ARRAY:
# RETURN THE SUB-ARRAY OF ELEMENTS THAT ARE $null
$psCustomObject.x -eq $null
При использовании в логическом контексте , например, в операторе if
, массивы , например, возвращаемые с LHS со значением массива, оцениваются следующим образом : Кончик шляпы PetSerAl за помощь.
- пустой массив или 1-элементный массив, содержащий пустой массив , оценивается как
$False
.
- 1-элементный массив, содержащий скаляр оценивает (подразумеваемое) логическое значение этого скаляра, например,
[bool] @(0)
фактически совпадает с [bool] 0
, то есть $False
.
- A 2 + -элементный массив или 1-элементный массив, содержащий непустой массив is всегда
$True
, независимо от его элементов 'значения (например,
[bool] ($False, $False)
и [bool] (, (, $False))
являются $True
.
Примечание: термин массив используется свободно выше. Строго говоря, вышесказанное относится к экземплярам любого типа, которые реализуют интерфейс [System.Collections.IList]
- см. исходный код .
В дополнение к массивам, это включает типы, такие как [System.Collections.ArrayList]
и [System.Collections.Generic.List[<type>]]
.
Пример того, когда два сравнения оцениваются по-разному в логическом контексте:
Примечание:
Этот пример несколько надуманный - сообщите нам, если есть лучшие.
Более простые примеры могут быть предоставлены с оператором -ne
.
Я не смог придумать пример для конкретного поведения, которое вы описываете, где $null -eq $psCustomObject.x
возвращает $True
, а $psCustomObject.x -eq $null
- нет. Если это действительно то, что вы видели, пожалуйста, сообщите нам конкретное значение .x
.
# Construct a custom object with an array-valued .x property that
# contains at least 2 $null values.
$psCustomObject = [pscustomobject] @{ x = @(1, $null, 2, $null) }
# $False, as expected: the value of .x is an array, and therefore not $null
[bool] ($null -eq $psCustomObject.x)
# !! $True, because because 2 elements in the input array (.x)
# !! are $null, so a 2-element array - ($null, $null) - is returned, which in a
# !! Boolean context is always $True.
[bool] ($psCustomObject.x -eq $null)
[1] В документах -replace
сгруппирован с операторами сравнения, и технически его RHS является массивом, но элементами этого массива являются по своей природе скалярные операнды: регулярное выражение для сравнения и строка замены.