Почему троичный оператор в Powershell не присваивает мою ценность? - PullRequest
3 голосов
/ 27 февраля 2020

Итак, у меня есть следующий скрипт powershell ... использующий троичный оператор в Powershell , и я начинаю сомневаться в его силе:

PS> $dasName="vCs01"

PS> $specialSubDerr @{
    "VCS01"="Derr";
    "VSC02"="dir";
    }

PS> $subDerr = @({"default"},{"$($specialSubDerr[$dasName.ToUpper()])"})[$specialSubDerr.contains($dasName.ToUpper())]
PS> $subDerr
"$($specialSubDerr[$dasName])"

PS> $($specialSubDerr[$dasName.ToUpper()])
Derr

Итак, в последних 2 строках выполняется, почему значение не присвоено $subDerr?

1 Ответ

3 голосов
/ 27 февраля 2020

с использованием троичного оператора Powershell

Ваш код не использует троичный оператор PowerShell, который доступен только в v7.0 + ; вместо этого он использует субоптимальную эмуляцию , которая объединяет 2-элементный массив с условным условием, логический результат которого отображается на индекс массива 0 (для $false) или 1 (для $true).
Помимо не являющегося концептуально очевидным , обходной путь неоптимален в том смысле, что он не закорачивает оценку альтернатив; то есть оба элемента массива безоговорочно оцениваются, прежде чем один из них выбран.

Примечание:

  • Не используйте @(...) для литералов массива - это не только не нужно, но и неэффективно в версиях PowerShell до 5.0, но, что более важно, вызывает концептуальную путаницу, ложно предполагая, что создает массивы - см. Нижнюю часть этого ответа .

  • Не используйте $(...) для отдельных команд или выражений , кроме внутри расширяемых строк ("...") и / или если вам нужно встроить несколько операторов в другой оператор.

  • PowerShell нечувствителен к регистру по умолчанию , поэтому нет необходимо нормализовать регистр ключей записей хеш-таблицы с помощью .ToUpper().

  • {...} определяет блок сценария , который является многократно используемым фрагментом Код PowerShell , который можно выполнить по требованию , позже , обычно через &, оператор вызова ; сам по себе блок сценария печатает в виде строкового значения , которое является буквальным содержимым между открытием { и закрытием }; do not использовать блоки скриптов как есть, если вы хотите вывести значения .


In PowerShell [Core] 7.0 + , вы можете использовать нуль-коалесцирующий оператор ??, чтобы получить то, что вы хотите:

$subDerr = $specialSubDerr[$dasName] ?? 'default'

Примечание: строго говоря выше, также выбирается 'default', если запись с ключом $dasName существует , но имеет значение $null.

В качестве альтернативы, с использованием троичного условного :

$subDerr = $specialSubDerr.Contains($dasName) ? $specialSubDerr[$dasName] : 'default'

В более ранних версиях с использованием эмуляции троичного условного выражения ( исправленная версия того, что вы пробовали):

$subDerr = ('default', $specialSubDerr[$dasName])[$specialSubDerr.Contains($dasName)]

или, более явно ( с коротким замыканием):

$subDerr = if ($specialSubDerr.Contains($dasName)) { $specialSubDerr[$dasName] }
           else                                    { 'default' }
...